Untitled

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 4686

Contents

Development and administration


New and planned
Get started
Learn
Business Central Learning Catalog
Discover all aka.ms links related to Business Central
Resources for partners
Business Central on Microsoft Training
Overview of business functionality
Business process walkthroughs
Scenarios for Contoso Coffeee Demo Data
Application design details
Develop
The SMB Opportunity for App Publishers
Get Started with Building Apps
Customize Business Central
The Lifecycle of Apps and Extensions
Update Lifecycle for Customizations
Maintain AppSource Apps and Per-Tenant Extensions
Discontinuing an AppSource app
Development of a Localization Solution
Microsoft Responsibilities
Components and Capabilities
Add your App to AppSource
AppSource Validation
Marketing Validation Checklist
Marketing Validation FAQ
Technical Validation Checklist
Technical Validation FAQ
How to Make Compelling Videos
How to Create an Effective Sales Landing Page
Embed Apps
Embed App Overview
Qualification and Onboarding
Deployment
Overview
Creating Deployment Packages
Managing Embed Apps in Microsoft Lifecycle Services
Using Application Family
Application Access Management
Application Access Management for ISVs and VARs
Application Access Management API
App Management
Introduction
App Management API
Upgrading an App Using ForceSync
Sell
Get Started as a Reseller of Business Central Online
Cloud Solution Provider (Partner Center)
Connect with customers (Partner Center)
Set Up Company Configuration Packages
Customize Business Central
Onboarding Experiences
Frequently asked questions
Frequently asked questions (general)
FAQ for Developing in AL
FAQ about Library and Dependency Apps in Business Central
FAQ about Testing your Business Central App
FAQ about Updating your Business Central App
FAQ about Managing and Submitting your Business Central Offer
FAQ for Marketing Validation
FAQ for Update Lifecycle for AppSource Apps
FAQ About the Windows Client and Business Central
FAQ about Connecting to Business Central Online from On-Premises Solutions
What's new or changed
Update 21.4
Update 21.3
Update 21.2
Update 21.1
Updates for earlier major versions
Update 20.6
Update 20.5
Update 20.4
Update 20.3
Update 20.2
Update 20.1
Update 19.5
Update 19.4
Update 19.3
Update 19.2
Update 19.1
Update 18.5
Update 18.4
Update 18.3
Update 18.2
Update 18.1
Update 17.5
Update 17.4
Update 17.3
Update 17.2
Update 17.1
Update 16.5
Update 16.4
Update 16.3
Update 16.2
Update 16.1
Update 15.4
Update 15.3
Update 15.2
Help and Support
Resources for Help and Support
Legal Resources
Technical Support
Help system
User Assistance Model
Configure the Help Experience
Configure Context-Sensitive Help
Custom Help Toolkit
Custom Help Toolkit: The FieldTopicTextExtractor tool
Extend and Collaborate on the Help
Authoring Guide
Migrate Legacy Help to the Business Central Format
Administration
Administration Overview
Understand Business Central online
Understanding the Infrastructure
Get Started as a Reseller of Business Central Online
Country/Regional Availability and Supported Translations
Delegated Administrator Access to Business Central Online
Trials and Subscriptions
Major Updates and Minor Updates
Version Numbers in Business Central
Operational Limits
Technical support of Business Central
Environment Types
Production and Sandbox Environments
Preparing Demo Environments
Preparing Test Environments
Prepare for Major Updates with Preview Environments
Admin center
Administration Center Overview
Manage environments
Manage access
Manage apps
Manage capacity
Manage notifications
Manage updates
Manage sessions
Copy a production or sandbox environment
Rename environments
Export databases
Restore an environment
Move an environment to another Azure Active Directory organization
Environment telemetry
Admin Center API
Overview
App Management
Authorized Azure AD Apps
Available Applications
Environments
Environment Database Export
Environment Outage Reporting
Environment Settings
Notifications
Reschedule Updates
Session Management
Support Settings
Telemetry
Entitlements and permissions
Licenses and entitlements
Entitlements and permission sets technical overview
Special permission sets
Prepare Business Central
Enabling new features ahead of time
Recommend apps
Set up Business Central
Get the Excel Add-in
Get the Outlook add-ins for the business inbox
Network configuration for the Excel add-in
Set up App Key Vaults for extensions
Deploy a tenant customization
Upgrading per-tenant extensions that conflict with other extensions
Upgrading AppSource apps in production
Set up standard company configuration packages
Apply company configuration packages
Onboard your customers
Trials and sign-ups
Onboarding experiences
Onboard new users with the welcome banner
Get users started with the checklist
Teaching tips and in-app tours for onboarding users
Pivot onboarding based on sign-up context
Recommend apps
Monitor and analyze telemetry
Overview
Available telemetry
Enable Telemetry
Control Telemetry Cost
Analyze Telemetry with Power BI
Analyze Telemetry with KQL
Alert on Telemetry
Telemetry by area
Overview
AppSource Submission Validation Telemetry
App Key Vault Secret Telemetry
Authorization Telemetry
Company Lifecycle Telemetry
Configuration Package Lifecycle Telemetry
Database Deadlock Telemetry
Database Lock Timeout Telemetry
Database Wait Statistics Telemetry
Email Telemetry
Environment Lifecycle Telemetry
Error Message Quality Telemetry
Error Method Telemetry
Extension Lifecycle Telemetry
Extension Update Telemetry
Feature Telemetry
Field Monitoring Telemetry
Job Queue Lifecycle Telemetry
Long Running AL Method Telemetry
Long Running SQL Queries Telemetry
Page View Telemetry
Permission Changes Telemetry
Permission Dependency Cycle Telemetry
Permission Error Telemetry
Profile Configuration Telemetry
Report Generation Telemetry
Retention Policy Telemetry
Stopped Sessions Telemetry
Table Index Telemetry
Task Scheduler Telemetry
User Checklist Telemetry
Verbose Logging Enabled/Disabled Telemetry
Web Service Access Key Telemetry
Web Service Requests Telemetry (Incoming)
Web Service Requests Telemetry (Outgoing)
Telemetry by Event IDs
Manage technical support
Manage technical support overview
Escalate support issues to Microsoft
Report customer outages
Analyze performance
Automation API
Overview
Automation company
Get automation company
Delete automation company
Create automation company
Update automation company
Company
Get company
Configuration package
Get configuration package
Delete configuration package
Create configuration package
Update configuration package
Extension
Get extension
Extension deployment status
Get extension deployment status
Extension upload
Get extension upload
Create extension upload
Update extension upload
Permission set
Get permission set
Scheduled job
Get scheduled job
User
Get user
Update user
User group
Get user group
Create user group
Delete user group
Update user group
User group member
Get user group member
Delete user group member
Create user group member
Update user group member
User permission
Get user permission
Delete user permission
Create user permission
Update user permission
Admin Center API
Overview
Cloud Migration API
Cloud Migration API Overview
Cloud migration company
Get cloud migration company
Update cloud migration company
Cloud migration status
Get cloud migration status
Cloud migration status detail
Get cloud migration status detail
Company
Get company
Setup cloud migration
Get setup cloud migration
Create setup cloud migration
Update setup cloud migration
Source product type
Get source product type
Subscriptions
Get subscriptions
Delete subscriptions
Create subscriptions
Update subscriptions
Table mapping
Get table mapping
Delete table mapping
Create table mapping
Update table mapping
Finance Reports API
Accounting period
Get accounting period
Business unit
Get business unit
Company
Get company
Customer
Get customer
Customer ledger entry
Get customer ledger entry
Detailed customer ledger entry
Get detailed customer ledger entry
Detailed vendor ledger entry
Get detailed vendor ledger entry
Dimension set entry
Get dimension set entry
Dimension value
Get dimension value
General budget entry
Get general budget entry
General ledger account
Get general ledger account
General ledger budgets
Get general ledger budgets
General ledger entry
Get general ledger entry
Subscriptions
Get subscriptions
Delete subscriptions
Create subscriptions
Update subscriptions
Vendor
Get vendor
Vendor ledger entry
Get vendor ledger entry
Migrate to Business Central Online
Migrate on-premises data
Migrate from Business Central on-premises
Migrate Dynamics GP data to the cloud
Migrate from Dynamics NAV
Define Migration Table Mappings
FAQ about migrating to Business Central online from on-premises solutions
Troubleshoot cloud migration
Compare Work in Dynamics GP to Business Central
Development
Development Overview
Get Started
Get Started with AL
Building Your First Sample Extension with Extension Objects, Install Code, and
Upgrade Code
Using Designer
Keyboard Shortcuts
AL Formatter
AL Outline View
AL Code Navigation
AL Code Actions
Object Ranges
Differences in the Development Environments
Adding Help Links from Pages, Reports, and XMLports
Working with Translation Files
Instrumenting an Application for Telemetry
Ready to Go
The SMB Opportunity for App Publishers
Get Started with Building Apps
The Business Central Online Learning Catalog
AppSource Validation
Marketing Validation Checklist
Technical Validation Checklist
How to Make Compelling Videos
Technical Validation FAQ
How to Create an Effective Sales Landing Page
Get Started with AL for On-Premises
Get Started with C/SIDE and AL Side-by-Side for On-Premises
Run C/SIDE and AL Side-by-Side
Create Runtime Packages for Business Central On-Premises
Development Environment
Configure the Development Environment
JSON Files
The Migration.json File
AL Language Extension Configuration
Resource Exposure Policy Setting
Develop for Multiple Platform Versions
Optimize Visual Studio Code for AL Development
Configure Projects and Workspaces
Work with Multiple AL Project Folders within One Workspace
Work with Multiple Projects and Project References
Code Analysis
The Code Analysis Tool
AL Compiler Diagnostics
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools with the Ruleset
AppSourceCop Analyzer Rules
CodeCop Analyzer Rules
PerTenantExtensionCop Analyzer Rules
UICop Analyzer Rules
Compile, Publish, and Debug
Compilation Scope Overview
Debugging in AL
Attach and Debug Next
Snapshot Debugging
Debug Upgrade and Install Code
AL Profiler
RAD publishing in AL
Sign an App Package File
Using Azure AD Authentication for Business Central On-Premises Installations
Testing
Overview
Test Codeunits and Test Methods
Handler Methods (for tests)
Test Runner Codeunits
Test Pages
UI Handlers
Application Testing Example
The Performance Toolkit Extension
FAQ about Testing your Business Central App
Work in Sandboxes
Sandbox Environments for Development
Get Started with the Container Sandbox Development Environment
Work with Development Sandboxes and Entitlements
Working with apps
App Identity
Choosing Runtime Version in AL
FAQ about Library and Dependency Apps in Business Central
Adding Data for Extensions
Other tools
The Txt2Al Conversion Tool
Viewing Table Data
Inspecting and Troubleshooting Pages
AL Language
A Tour of the AL language
FAQ for AL Developers
Program building blocks
System-Defined Variables
Statements
Simple Statements
Control Statements
Access Modifiers
Comments
Language Elements
Data Types
Overview
Simple Types
Date and Time
Numbers
Strings
Boolean
Guid
Complex Types
Blob
Media
MediaSet
Record
System
JSON and XML Types
JsonArray Data Type
JsonObject Data Type
JsonToken Data Type
JsonValue Data Type
XmlAttribute Data Type
XmlAttributeCollection Data Type
XmlCData Data Type
XmlComment Data Type
XmlDeclaration Data Type
XmlDocument Data Type
XmlDocumentType Data Type
XmlElement Data Type
XmlNamespaceManager Data Type
XmlNameTable Data Type
XmlNode Data Type
XmlNodeList Data Type
XmlText Data Type
Object types
Other Types
Joker Data Type (Internal)
Collections
Array
Dictionary
List
Enumerations and Options
Enum
Option
Interfaces
Methods
Progress Windows, Message, Error, and Confirm Methods
Method Attributes
Using Data Types in methods
Overloading methods
Handler Methods (for tests)
Objects
Object Properties
Table
Table Extension Object
Table Keys
Page
Page Extension Object
Page Customization Object
Report
Profile
Codeunit
Query
XMLPort
Control Add-In
Entitlement
Permission Set
Permissionset
Permissionset Extension
Test Codeunits
Test Runner Codeunits
Triggers
Error Handling
Error Handling
Handling Errors using Try Methods
Collecting Errors
Error(String [, Any,...]) Method
Error(ErrorInfo) Method
LogInternalError(String, DataClassification, Verbosity) Method
LogInternalError(String, String, DataClassification, Verbosity) Method
Formatting Values
Formatting Decimal Values in Fields
Formatting Values, Dates, and Time
Tables and Data
Overview
Defining table structures
Tables Overview
Table Object
System Fields
Table Extension Object
Setting Relationships Between Tables
Classifying Data
Modifying Data
Insert, Modify, ModifyAll, Delete, and DeleteAll Methods
Temporary Tables
Retaining Table Data after Publishing
Enabling Sales Tables for Extension Development
Creating Filter Pages for Tables
Working With Media on Records
Reading Data
Get, Find, and Next Methods
Partial Records
Using Partial Records
FAQ
Query Objects
Queries Overview
Query Object
Linking and Joining Data Items
Filtering
Aggregating Data
Retrieving Date Data
Using Queries Instead of Record Variables
Accessing Columns of a Query Dataset
Tranferring Data
Importing and Exporting data
XMLport Overview
XMLport Object
Defining an XMLport Schema
Using Namespaces with XMLports
Request Pages
Pages and User Interfaces
Customizing for User Roles
Inspecting and Troubleshooting Pages
Role Centers
Designing Role Centers
Sample Role Center
Adding links to the Navigation menu
Adding a checklist to the Role Center
Headlines
Cues and Action Tiles
Pages
Pages Overview
Page Object
Page Extension Object
Adding Pages to Tell Me
Page Types and Layouts
List Pages
Designing List Pages
Sample List Page
Repeater Controls
Displaying Data as Tiles
Views
Adding Filter Tokens
Designing Indented Lists
Adding Teaching Tips to List Pages
Card Pages
Designing Card Pages
Sample Card Page
Adding Teaching Tips to Card Pages
Assisted Setup Guides
Page Parts
Parts Overview
Designing List Parts
Designing Card Parts
Designing Headline Parts
Designing Power BI Report Parts
FactBoxes
Fields
Arranging Fields on a FastTab
Grid Control
Fixed Control
Field Groups
CalcFields, CalcSums, FieldError, FieldName, Init, TestField, and Validate
Methods
Formatting Decimal Values in Fields
Actions
Actions in AL
Adding Actions to a Page
Actions in the User Interface
Promoted Actions
Promoted Actions
Organizing Promoted Actions
Common Promoted Action Groups
Modern Action Bar
Action Bar Improvements
Behavioral Changes for Promoted Actions
Pages with Action Bar Improvements
Profiles
Designing Profiles
Profile Object
Page Customization Object
Using the Client to Create Profiles
Control Add-ins
Control Add-in Style Guide
Developing for the Business Central Mobile App
Introducing the Business Central Mobile App
Deciding on Your Tablet and Phone Strategy
Get Started Developing for the Business Central Mobile App
Designing for Different Screen Sizes on Tablet and Phone
Differences and Limitations When Developing Pages for the Mobile App
Opening the Business Central Tablet or Phone Client from a Browser
Example: Developing a Sales Rep Role Center for the Tablet Client
Permissions and Permission Sets
Overview
Composing Permission Sets
Permissionset Object
Permissionset Extension Object
Permissions on Database Objects
Inherent Permissions
Exporting Permission Sets to XML
Events
Event Types
Publishing Events
Raising Events
Subscribing to Events
Isolated Events
Discover Events Using the Event Recorder
Event Example
Walkthrough: Implementing New Workflow Events and Responses
Notifications
Developing Reports
Overview
Report Design Overview
Report Object
Report Extension Example
Defining a Report Dataset
Request Pages
Report Triggers and Operations
Adding Reports to Tell Me
Substituting a Report
Testing a Report
Report Layouts
Creating a Word Layout Report
Creating an RDL Layout Report
Creating an Excel Layout Report
Defining Multiple Report Layouts
Defining a Custom Report Render
Walkthrough: Designing a Report from Multiple Tables
Adding Barcodes
Formatting Decimal Values in Fields
Handling Security
Permission Sets and Entitlements Overview
Permissionset Object
Permissionset Extension Object
Permissions on Database Objects
Inherent Permissions
Exporting Permission Sets to XML
Entitlement Object
Running Things in the Background
Page Background Tasks
Developing APIs
API Page Type
API Queries
Accessing Device Capabilities
Implementing Camera in AL
Implementing Location in AL
Compiler Directives
Region Directive
Pragma Directive
AL Programming
Overview
Programming in AL
FAQ for Developing in AL
AL Simple Statements
AL Control Statements
AL Complex Types
AL Error Handling
Working with AL Methods
System-Defined Variables
Preprocessor Directives in AL
Region Directive
Pragma Directive
Using Access Modifiers in AL
XML Comments in Code
Code Analysis
Using the Code Analysis Tool
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools with the Ruleset
AppSourceCop Analyzer Rules
CodeCop Analyzer Rules
PerTenantExtensionCop Analyzer Rules
UICop Analyzer Rules
Isolated Storage
File Handling and Text Encoding
Flowfields
FlowFields and FlowFilters
Nonclustered Columnstore Indexes (NCCI)
NCCI Overview
NCCI and SQL Server
NCCI Tuning and Tracing
NCCI Performance
Migrating from SIFT to NCCI
SumIndexField Technology (SIFT)
SIFT Overview
SIFT and SQL Server
SIFT Tuning and Tracing
SIFT Performance
Number Sequences
Extensible Enums
Protected Variables
Working with labels
Objects
Table Object
Table Extension Object
Table Keys
Enums
Page Object
Page Extension Object
Page Customization Object
Report Object
Profile Object
Codeunit Object
Query Object
XMLPort Object
Control Add-In Object
Entitlement Object
Permissionset Object
Permissionset Extension Object
AL Platform
Overview
Using the System Application
Overview of the System Application
Application Reference for Dynamics 365 Business Central
Creating New Modules in the System Application
Module Architecture
Get Started with Modules
Set Up Your Development Environment
Create a New Module
Create a .NET Wrapper Module
Change a Module
Task Scheduler and Job Queue
Task Scheduler
Job Queue
App Key Vaults for Secrets
Overview
Setting up App Key Vaults for Online
Setting up App Key Vaults for On-premises
Using Key Vault Secrets in Extensions
Developing Printer Extensions
Printer Extension Overview
Creating a Printer Extension
Creating Deep Links
Web Client URL
Business Central App URL
Instrumenting with Telemetry
Overview
Creating Custom Events for Application Insights
Sending Extension Telemetry to Application Insights
Adding Feature Usage Telemetry
Creating Custom Events for Event Log (On-premises only)
Using .NET (on-premises only)
Get started with Microsoft .NET Interoperability from AL
Migrating from .NET Framework to .NET Standard
.NET Control Add-Ins
Subscribing to Events in a .NET Framework Type
Serializing .NET Framework Types
Extensibility
Extending the Base Application
Application Reference for Dynamics 365 Business Central
The Microsoft_Application.app File
Publishing a Code-Customized Base Application
Extending Application Areas
Examples
Extending Item Charge Distribution Methods
Extending Price Calculations
Extending Pages Previously Based on the Date Virtual Table
Extending Data Archiving
Extending Document Sharing and OneDrive Integration
Extending Customer, Vendor, and Item Templates
Extending Email Capabilities
Extending G/L Entry Aggregations When Posting Invoices
Using Events
Event Types
Publishing Events
Raising Events
Subscribing to Events
Isolated Events
Discover Events Using the Event Recorder
Event Example
Walkthrough: Implementing New Workflow Events and Responses
Notifications
Developing Client Add-ins
Control Add-in Style Guide
Control Add-in Best Practices
Adding Power BI Report Parts to Pages
Rules, Guidelines, and Best Practices
Overview
Deprecating AL Code
Using a Prefix or Suffix
Instrumenting an Application for Telemetry
Testing your Extension
User Scenario Documentation
Restrictions on UI for Objects Exposed as Web Services
Replacing OnBeforeCompanyOpen and OnAfterCompanyOpen
Move from OnCompanyOpen
Walkthrough: Building an Advanced Sample Extension
Walkthrough: Testing the Advanced Sample Extension
Best Practices
Overview
AL Code
Rules and Guidelines
Naming Conventions
Using a Prefix or Suffix
Deprecating AL Code
Restrictions
Restrictions on UI for Objects Exposed as Web Services
Replacing OnBeforeCompanyOpen and OnAfterCompanyOpen
Move from OnCompanyOpen
Telemetry
Adding Custom Telemetry
Adding Usage Telemetry
Code Deprecation
User Scenarios
Requirements for Connectivity Apps
Testing
Testing your Extension
Building an Advanced Sample Extension
Testing the Advanced Sample Extension
Performance
Performance Developer Guide
Analyzing Performance
Security
Application Security
Data Security
Using Key Vaults for Secrets
Extension Lifecycle
Overview
Migration
Generating Delta Files
Migrating Tables and Fields Between Extensions
Data Migration Overview
Moving Tables and Fields Down
Moving Tables and Fields Up
Migration.json File
Translation
Translations Overview
Working with Translation Files
Testing
Overview
Test Codeunits and Test Methods
Handler Methods (for tests)
Test Runner Codeunits
Test Pages
UI Handlers
Application Testing Example
The Performance Toolkit Extension
FAQ about Testing your Business Central App
Deploying and Installing
Maintain AppSource Apps and Per-Tenant Extensions
FAQ about Managing and Submitting your Business Central Offer
Writing Extension Install Code
Publish and Install an Extension
Upgrading AppSource Apps in Production
Updating
Overview
Update Lifecycle for Customizations
Update Lifecycle for AppSource Apps FAQ
FAQ about Updating your Business Central App
Upgrading Extensions
Deprecating code
Microsoft Timeline for Deprecating Code in Business Central
Best Practices for Deprecation of AL Code
Deprecating Explicit and Implicit With Statements
DevOps with AL-Go for GitHub
AL-Go Overview
Create a New Per-Tenant Extension and Start Developing in Visual Studio Code
Add a Test App to an Existing Project
Register a Customer Sandbox Environment for Continuous Deployment using S2S
Create a Release of Your Application
Register a Customer Production Environment for Manual Deployment
Update AL-Go System Files
Use Azure KeyVault for Secrets with AL-Go
Create Online Development Environment from Visual Studio Code
Create Online Development Environment from GitHub
Set up CI/CD for an Existing Per-Tenant Extension
Set up CI/CD for an Existing AppSource App
Enable KeyVault Access for Your AppSource App during Development and/or Test
Set up Your Own GitHub Runner to Increase Build Performance
Introducing a Dependency to Another GitHub Repository
Enabling Telemetry for AL-Go Workflows and Actions
Troubleshooting
Overview
Troubleshooting in the client
Using the Page Inspector
Using the Event Recorder
Database Table Information
Database Locks
Missing Indexes
Database Wait Statistics
Using the Performance Profiler
Verifying Report Datasets
Checking Personalization Issues
Troubleshooting user personalization can't be started
Checking Customization Issues
Troubleshooting profile configuration can't be started
Verifying User Permissions
Investigating Mobile App (On-Premises)
Troubleshooting in AL
Debugging AL code
Capturing Snapshots
Using the AL Profiler
Investigating Printer and Report Payloads
Inspecting and Troubleshooting Pages
Troubleshooting Performance Issues
Troubleshooting with telemetry
Overview
Available telemetry
Enabling Telemetry
Using Jupyter notebook troubleshooting guides
Using Power BI troubleshooting reports
Using telemetry to investigate Performance Issues
AL Language Reference
Security, Privacy, and Compliance
Security
Security Overview
Tips for Business Users
Application
Online
On-Premises
Data Security
Azure security service tags
Privacy
Privacy FAQ
Privacy (microsoft.com)
Compliance
Compliance Overview
Service Overview
Performance
Performance Overview
Application
Tips for Business Users
Developer
Online
On-Premises
How to Work with a Performance Problem
Integration
Refactor Integration Management
Web Services
Web Services Overview
Terms of Use for Web Services
General
Publishing a Web Service
Handling UI Interaction
Managing Timezones
Working with Static Proxy
Authentication
Authentication with OAuth
Service-to-Service Authentication
Walkthrough: Creating a console application that uses OAuth
Securing Remote Connections Using Certificates
Supported Cipher Suites
Best Practices
APIs
Overview
Business Central API (v2.0)
Business Central API (v1.0)
Automation API
Admin Center API
Cloud Migration API
Developing a Custom API
Getting a List of Environments
OData
Overview
OData Query Performance
Authentication with OAuth
Return or Obtain an AtomPub Document
Return or Obtain Service Metadata EDMX Document
Return or Obtain a JSON Document
Using Filter Expressions in OData URIs
Using FlowFilters in OData URIs
Server-Driven Paging
Containments and Associations
Using OData on Queries Set with Top Number of Rows
Using OData to Modify Data
Using OData Transactional $batch Requests
Creating and Interacting with an OData V4 Bound Action
Known OData Limitations
SOAP
Overview
SOAP Service URIs
Authentication with OAuth
Basic Operations
Create
CreateMultiple
Delete
Delete_<part>
GetRecIdFromKey
IsUpdated
Read
ReadByRecId
ReadMultiple
Update
UpdateMultiple
Retrieving Companies
Indicating that a value exists in field
Connect Apps
Developing Connect Apps
Tips for working with the APIs
Using Filters with API calls
Developing a Custom API
Service-to-Service Authentication
Integrating with Microsoft Dataverse
Custom Integration with Dataverse
Custom option mappings with Dataverse
AL Proxy Table Generator
Dataverse API
Business Central Dataverse API
Company
Get company
Dataverse entity change
Get dataverse entity change
Create dataverse entity change
Subscriptions
Get subscriptions
Delete subscriptions
Create subscriptions
Update subscriptions
Integrating with Microsoft Power Automate
Power Automate Integration Overview
Set Up Power Automate Integration
Set Up Automated Flows
Set Up Instant Flows
Manage Power Automate Flows
Integrating with Microsoft Power BI
Adding Power BI Report Parts to Pages
Integrating with Microsoft Power Platform
Microsoft Power Platform Integration with Business Central
Table Modeling
Application Lifecycle Management for Solutions that use Virtual Tables
Business Central and Microsoft Dataverse Admin Reference
FAQ
Integrating with Microsoft Teams
Overview
Extend Teams Cards
Tabs
Add Business Central Tabs
Add and Remove Recommended Content
Get relevant session and environment details
FAQ
Business Central API (v2.0)
Removed or deprecated features
Deprecated Features in the Application
Deprecated Features in the Base App
Deprecated Fields, and Fields Marked as Obsolete in Local Functionality
Deprecated Features in the Austrian Version
Deprecated Features in the Belgian Version
Deprecated Features in the Canadian Version
Deprecated Features in the Czech Version
Deprecated Features in the Dutch Version
Deprecated Features in the Finnish Version
Deprecated Features in the German Version
Deprecated Features in the Icelandic Version
Deprecated Features in the Italian Version
Deprecated Features in the Mexican Version
Deprecated Features in the Norwegian Version
Deprecated Features in the Russian Version
Deprecated Features in the Swedish Version
Deprecated Features in the Swiss Version
Deprecated Features in the UK Version
Deprecated Features in the United States Version
Deprecated Features in the Platform
Deprecated Tables
Deprecated Tables
Deprecated Tables in the India Version
Deprecated Code
Microsoft Timeline for Deprecating Code in Business Central
Best Practices for Deprecation of Code in the Base App
Deprecating Explicit and Implicit With Statements
Business Central on-premises
Legal Resources
Deployment
Deployment Overview
Features not implemented in on-premises deployments
System Requirements
2022 Release Wave 2
2022 Release Wave 1
2021 Release Wave 2
2021 Release Wave 1
2020 Release Wave 2
2020 Release Wave 1
2019 Release Wave 2
April 2019
Software lifecycle policy and on-premises releases
FAQ About the Windows Client and Business Central
Dynamics 365 Business Central On-Premises Updates
2022 Release Wave 2 On-Premises Updates
2022 Release Wave 1 On-Premises Updates
2021 Release Wave 2 On-Premises Updates
2021 Release Wave 1 On-Premises Updates
2020 Release Wave 2 On-Premises Updates
2020 Release Wave 1 On-Premises Updates
2019 Release Wave 2 On-Premises Updates
Spring 2019 On-Premises Updates
October 2018 On-Premises Updates
Running a Container-Based Development Environment
Components
Planning
Deployment Topologies
Deployment Topologies Overview
Deploying Demonstration Environment
Deploying Single-Computer
Deploying on Two-Computers
Deploying on Three Computers
Installing Using Setup
Provisioning a Service Account
Securing Remote Connections Using Certificates
Business Central Web Server
Business Central Web Server Overview
Configuring Web Server Instances
Configure IIS
Configure SSL
Setting Up Multiple Web Server Instances
Configure Business Central Web Server to Accept Host Names
Configuring Delegation
Multitenant Deployment
Architecture Overview
Setup Guide
Migrating From Single to Multitenancy
Overview
Separating Application Data from Business Data
Database
Installation Considerations for SQL Server
Configuring Database Authentication
Creating Application and Tenant Databases
Configuring and Troubleshooting Connections
Deploying to Azure SQL Database
Reducing Database Size
Business Central Mobile App
Introducing the Mobile App
Preparing For and Installing the Mobile App
Troubleshooting the Mobile App On-Premises
Using HTTPS and Certificates in Business Central Mobile App
Administration
Administration of Business Central On-Premises
Server Administration Tool
Administration Shell
Windows PowerShell Cmdlets
Windows PowerShell Cmdlets for Business Central
Administration Cmdlets
Administration Cmdlets for Extensions
Development Cmdlets
Development Cmdlets for Extensions
Configuring User Authentication
Authentication and Credential Types
Authenticating with Azure Active Directory
Overview
Configure Azure AD Authentication with OpenID Connect
Configure Azure AD Authentication with WS-Federation
Authenticating with NavUserPassword
Configuring Business Central Server
Configuring Business Central Web Server
Configuring Business Central Web Server Instances
Setting Up Multiple Web Server Instances
Configuring Database Authentication
Encrypting Data
Setting up the Excel Add-In
Setting Up the Add-In for Outlook Integration
Setting up App Key Vaults for Extensions
Configuring Business Central Database
Optimizing SQL Server Performance
Compatibility Level
Using Table Partitioning and Data Compression
Configuring Read Scale-Out
Monitoring Business Central Server
Monitoring Performance Counters
Monitoring Server Events
Monitoring Server Events Overview
Trace Events List
Admin and Operational Events List
Using Event Viewer
Using Performance Monitor
Using PerView
Using LogMan
Using PowerShell
Turn Off or Limit Telemetry
Analyzing Database Performance
Monitoring Long Running SQL Queries
Troubleshooting: Analyzing Long Running SQL Queries Involving FlowFields
Troubleshooting: Using the Event Log to Monitor Long Running SQL Queries
Monitoring and Analyzing Using Telemetry
Telemetry Overview
Enabling Application Insights
Understanding Session Timeouts
Preparing Dynamics 365 for Sales for Integration
Registering Your Deployment on Azure
Upgrade
Upgrading to Business Central
Supported Upgrade Paths
Business Central 2022 Release Wave 2
Overview
Before You Upgrade
Upgrade Compatibility Matrix
Upgrading Permission Sets
Upgrading Reports
Application and Data
From version 14 Unmodified C/AL Application
From version 14 Customized C/AL Application
From Version 15 and Later
Related Articles
Convert to AL
Migrating Tables and Fields Between Extensions
Data Migration Toolkit - India
Technical Upgrade
From Version 14
From Version 18 or 19
From Version 20
Installing a Minor Update
Business Central 2022 Release Wave 1
Overview
Upgrade Compatibility Matrix
Upgrading Permission Sets
Upgrading Reports
Application and Data
From version 14 Unmodified C/AL Application
From version 14 Customized C/AL Application
From Version 15 and Later
Related Articles
Convert to AL
Migrating Tables and Fields Between Extensions
Data Migration Toolkit - India
Technical Upgrade
From Version 14
From Version 17, 18, or 19
Installing a Minor Update
Business Central 2021 Release Wave 2
Overview
Upgrade Compatibility Matrix
Upgrading Permission Sets
Application and Data
From version 14 Unmodified C/AL Application
From version 14 Customized C/AL Application
From Versions 15 and Later
Related Articles
Convert to AL
Migrating Tables and Fields Between Extensions
Data Migration Toolkit - India
Technical Upgrade
From Version 14
From Version 16, 17, or 18
Installing a Minor Update
Business Central 2021 Release Wave 1
Overview
Upgrade Compatibility Matrix
Upgrading Permission Sets
Application and Data
From version 14 Unmodified C/AL Application
From version 14 Customized C/AL Application
From Version 15, 16, or 17 Microsoft Base Application
Related Articles
Convert to AL
Migrating Tables and Fields Between Extensions
Technical Upgrade
From Version 14
From Version 15, 16, or 17
Installing a Minor Update
Earlier Versions
Business Central 2020 Release Wave 2
Overview
Upgrade Compatibility Matrix
Application and Data
From version 14 Unmodified C/AL Application
From version 14 Customized C/AL Application
From Version 15 Microsoft Base Application
From Version 16 Microsoft Base Application
Convert to AL
Migrating Tables and Fields Between Extensions
Technical Upgrade
From Version 14
From Version 15
From Version 16
Installing a Minor Update
Business Central 2020 Release Wave 1
Upgrade Overview
Upgrade Compatibility Matrix
Application and Data
From version 14 Unmodified C/AL Application
From version 14 Customized C/AL Application
From Version 15 Microsoft Base Application
Convert to AL
Migrating Tables and Fields Between Extensions
DestinationAppsForMigration
Technical Upgrade
From Version 14
From Version 15
Installing a Minor Update
Business Central 2019 Release Wave 2
Upgrade Overview
Upgrade Compatibility Matrix
Upgrade of an Unmodified Application
Technical Upgrade of a Customized Application
Installing a Minor Update
Business Central Spring 2019
Upgrade Overview
Before You Upgrade
Transitioning From Codeunit 1
Technical Upgrade
Technical Upgrade
Technical Upgrade Quick Reference
Application and Data Upgrade
Upgrading the Application Code
Upgrading the Data: Single-Tenant Mode
Upgrading the Data: Single-Tenant Mode
Quick Reference
Upgrading the Data: Multitenant Mode
Upgrading the Data: Multitenant Mode
Quick Reference
Installing a Minor Update
Some Known Issues
Migrate Legacy Help to the Business Central Format
Development and Administration for Dynamics 365
Business Central
2/6/2023 • 6 minutes to read • Edit Online

Dynamics 365 Business Central is a complete enterprise resource planning (ERP) software solution for mid-
sized organizations that is fast to implement, easy to configure, and simple to use. Right from the start,
simplicity has guided — and continues to guide — innovations in product design, development,
implementation, and usability. Users can customize and administrate their Business Central experience in the
product. Other tasks for administration and development require a more specialized profile, and in this
Development and Administration section, you can find more technical information, including information about
developing for Dynamics 365 Business Central using the AL Language extension and Visual Studio Code.

Get started with development and administration documentation


The content in this section of the learn.microsoft.com site is intended for people who are Business Central
resellers, administrators, or developers, and people who want to get started with Business Central development
or administration. If you are a functional consultant or user of Business Central, check out the Business
Functionality Help instead.

Resources for an administrator


As a system administrator, IT professional, or superuser, you have tools available for you to configure, update,
and maintain a Business Central solution. The tools and processes are somewhat different depending on
whether Business Central is deployed online or on-premises. It also depends on whether you are an internal
administrator, or you work for a partner.
The following table outlines recommended content for you to get started:

L IN K DESC RIP T IO N

Deployment of Dynamics 365 Business Central Describes the difference between making Business Central
available online and on-premises.

Administration of Business Central Online as an internal Learn about resources that are available to you as the
administrator system administrator, IT professional, or superuser of a
Business Central customer.

Administration of Business Central Online as a partner Learn about resources that are available to you as a Business
Central reselling partner.

The Business Central Administration Center Learn about the administration center and what you can do
there.

Technical Support for Dynamics 365 Business Central Learn about the tools that are available to you to help you
troubleshoot your customers' Business Central.

Managing Technical Support Learn about how to handle support requests.


L IN K DESC RIP T IO N

Administration of Business Central On-Premises Learn about resources that are available to you as the
system administrator, IT professional, or superuser of
Business Central on-premises.

Configuring the Help Experience Learn about your options for deploying Help for Business
Central.

Resources for a developer


You can extend Business Central with add-on apps, vertical or horizontal solutions, and with integration to other
products and services.
The following table outlines recommended content for you to get started:

L IN K DESC RIP T IO N

Developer learning paths on Microsoft Learn Provides links to role-specific training.

Development in AL Get an understanding of the basics and terms you will


encounter while working in Visual Studio Code with the AL
extension.

Get Started with AL Learn how to set up a development environment.

The SMB Opportunity for App Publishers Learn about the business opportunity for building your app
on top of Business Central.

Get Started with Building Apps Learn how to get started as a partner.

Resources for a reseller


As a reseller of Business Central online, your route to get started depends on whether you are already familiar
with Business Central on-premises or its predecessor, Dynamics NAV, or if you are already familiar with the
Cloud Solution Provider program. The following table outlines recommended content for you to get started:

L IN K DESC RIP T IO N

Get Started as a Reseller of Business Central Online Landing page for readiness for resellers.

Business Functionality in Business Central Landing page for the core functionality in Business Central.

Business Central on Microsoft Learn Provides links to role-specific training.

Enroll in the Cloud Solution Provider program Describes the different models for selling in the Cloud
Solution Provider (CSP) program so you can determine
which works best with your business.

Enroll in the CSP program


The Cloud Solution Provider (CSP) program helps your company to be more involved in your customers'
businesses, beyond reselling licenses. In CSP, you can choose to enroll as an indirect reseller or a direct bill
partner.
In most cases, you will enroll as an indirect reseller and then work with an indirect provider, also referred to as a
distributor, who then manages all interaction with Microsoft in terms of licensing and technology, so that you
can focus on sales and support. If you decide to enroll as a direct bill partner in order to fully own the end-to-
end relationship with both customers and Microsoft, make sure that you meet the eligibility requirements. For
more information, see Enroll in the Cloud Solution Provider program in the Microsoft Partner Center content.
The Microsoft Partner Center is a generic portal where partners can sell and manage customer subscriptions for
Microsoft services, such as Microsoft 365, Azure, Dynamics 365, and others, as well as for some third-party
products. For more information, see the Partner Center documentation.
Some indirect providers (distributors) provide their resellers with a custom portal that optimizes and enhances
the experience beyond the Partner Center. They can also provide indirect resellers with an API to automate some
of the customer onboarding steps. Contact your indirect provider to find out more.
Both indirect resellers and direct bill partners can access and support their customers' Business Central by
setting up a reseller relationship with them.
To service customers in a specific country, your partner company's Azure Active Directory (Azure AD) tenant and
CSP account must be registered in the regional CSP market that covers that country. For more information, see
Cloud Solution Provider program regional markets and currencies.

NOTE
When you buy Business Central offers on behalf of your CSP customers, the CSP offer must be available in both your own
tenant's country and in your customer's tenant's country. For example, if your tenant is located in Slovakia and the
customer's tenant is in Germany, you will not be able to sell Dynamics 365 Business Central Premium to that customer,
because this offer is currently not available in Slovakia.
Similarly, if your tenant is located in Germany and the customer's tenant is in Slovakia, you will not be able to sell
Dynamics 365 Business Central Premium to that customer, because this offer is currently not available in Slovakia.

Other roles and profiles


Business Central supports the same profiles and roles as other Dynamics 365 services. If you see yourself as a
solution architect or functional consultant, for example, Business Central has functionality and content for you.
Look around in the Help & Support section here, for example, ramp up on features in the business functionality
content, or learn how you can integrate this with other products.
If you are completely new to Business Central, we recommend you take the Get started learning path.

Get notified about changes through an RSS feed


To subscribe to a Really Simple Syndication (RSS) feed of all updates that are to the content on
learn.microsoft.com across the developer and administration content for Business Central, use the following
link:
RSS feed

NOTE
The RSS feed returns a list of the 100 articles most recently updated. The list is sorted by date, but it can take up to a
week before the most recently updated articles make it to the list.

See also
Dynamics 365 Business Central Business Functionality Help
Dynamics 365 Business Central on Microsoft Learn
FAQ for Dynamics 365 Business Central Development and Administration
Resources for Help and Support for Dynamics 365 Business Central
The Lifecycle of Apps and Extensions
Maintenance of AppSource Apps and Per-Tenant Extensions
Microsoft Dynamics 365 Business Central on the Dynamics 365 blog
Dynamics 365 Business Central Partner Portal
Dynamics NAV Developer and ITPro Content
Dynamics 365 Product Licensing
Welcome to Business Central | Resources for
Partners
2/6/2023 • 3 minutes to read • Edit Online

Are you a Microsoft partner working with Business Central and looking for relevant resources? Find everything
you need in this article and remember to bookmark aka.ms/BCAll.

Hot topics right now


Watch the Business Central Launch Event on aka.ms/BCLE
Access Business Central with your Microsoft 365 license. Read about it here
New CSP customer promotion for Business Application. Check out the new promo for new and existing
legacy customers here
New 'Do more with less' page on Partner Portal, which features partner resources to differentiate your
practice, support migrations, drive customer conversations and much more. Find it here

Latest release and updates


Business Central release plan: aka.ms/BCReleasePlan
Major updates: aka.ms/BCUpdates
Minor updates: aka.ms/BCLastMinorUpdate
Missing a feature? Post or vote for ideas on: aka.ms/BCIdeas

Stay up to date
Discover what's new for partners in the Business Central newsletter: aka.ms/BCNews
Watch the what’s new launch event sessions: aka.ms/BCLE
Join the office hours calls: aka.ms/BCOfficeHours
Find on-demand recordings of office hours calls: aka.ms/BCOfficeHoursRecordings

Social and blogs


Stay tuned about what’s going on in the #MSDyn365BC community: twitter.com/MSDYN365BC (Use
#BCALHelp on Twitter for quick hints on how to do things)
Be a part of the community for Business Central: community.dynamics.com/business
Blog for IT professionals: cloudblogs.microsoft.com/dynamics365/it/product/business-central
Blog for decision makers: cloudblogs.microsoft.com/dynamics365/bdm
Join the Business Central development group on Yammer: aka.ms/BCYammer

Partner readiness and programs


Get started as a partner (reselling Business Central): aka.ms/BCReseller
Essential partner resources (marketing material): aka.ms/BCPartnerPortal
Browse all Business Central learning courses: aka.ms/BCLearn
Supported countries, regions, and languages: aka.ms/BCCountries
Join the conversation on Yammer for partners: aka.ms/BCYammer
Online or in-person training and coaching for Business Central. Contact an ISV Development Center:
aka.ms/ISVDevCenter
The Universal Code Initiative: aka.ms/BCUniversalCode

Go to market
Business Central homepage: dynamics.microsoft.com/business-central/overview/
Try Business Central for free (30-day trial): go.microsoft.com/fwlink/?LinkId=2143349&clcid=0x409
Business Central customer stories: aka.ms/BCCustomerStories
Discover useful resources for partners: aka.ms/BCPartnerPortal
Transact capability for Business Central Apps on Microsoft AppSource: aka.ms/BCAppTransact

Customer onboarding and resources


Discover all Business Central apps on AppSource: aka.ms/BCAppSource
Get Business Central on your mobile devices: aka.ms/BusinessCentralApp
Get Business Central installable app on your desktop: aka.ms/BCPWA
Learn about onboarding experiences in Business Central: aka.ms/BCOnboarding
Productivity tips: aka.ms/BCProductivity
Keyboard shortcuts: aka.ms/BCKeys

Reporting and Business intelligence


Get started with reporting: aka.ms/BCReporting
Excel layout samples: aka.ms/BCExcelSamples
Business Central and Power BI: aka.ms/BCPBI

Power Platform
Business Central and Power BI: aka.ms/BCPBI
Business Central and Power Automate: aka.ms/BCAutomate
Business Central and Power Apps: aka.ms/BCPApps
[Prototype] Low code sync of Business Central entities to Dataverse: aka.ms/bc2dataverse

Migrating from on-premises to cloud (online)


Discover assets for transitioning Dynamics GP, Dynamics NAV, Dynamics SL, Business Central on-premises
customers to Business Central online: aka.ms/BCMigrations
Use migration tooling: Migrate Data

Getting support
Managing technical support for customers: Manage Technical Support
Test network connectivity for Business Central: aka.ms/BCCP

Developing for Business Central in general


Get started with developing apps: aka.ms/BCPublisher
Business Central technology samples: aka.ms/BCTech
Maintain your app(s): Maintain Your App
Use the GitHub forum to post questions about Visual Studio Code and AL Language to the community and
Microsoft experts: github.com/microsoft/al/issues
Preview for next major update: aka.ms/BCMajorUpdates
Ask your questions related to app development in the App Development group on Yammer:
aka.ms/BCYammer
Get the latest preview version and give feedback: aka.ms/Collaborate (learn how you join relevant
engagements here)
Build solutions that link to Business Central mobile app: aka.ms/BCProtocol

Developing apps for AppSource


AppSource marketing checklist: aka.ms/AppSourceGo
AppSource technical checklist: aka.ms/CheckBeforeYouSubmit
AppSource technical FAQ: aka.ms/TechValidationFAQ
Set up DevOps for your AppSource apps: aka.ms/AL-Go-AppSource
Ask your question related to AppSource in the AppSource group on Yammer: aka.ms/BCYammer
Development of a localization app: aka.ms/BusinessCentralLocApps

Developing customer specific solutions


Set up DevOps for your customer projects: aka.ms/AL-Go-PTE

Telemetry and performance


App performance documentation: aka.ms/BCPerformance
Telemetry documentation: aka.ms/BCTelemetry
Telemetry samples: aka.ms/BCTelemetrySamples
Analyze environment telemetry data with Power BI: aka.ms/BCTelemetryReport
Analyze app telemetry data with Power BI: aka.ms/BCTelemetry-Isv-App

Security, Privacy, and Compliance


Security and Privacy documentation: aka.ms/BCSecurity
Application compliance: aka.ms/BCAppCompliance

Licensing and Pricing


Business Central licensing guide
Business Central Universal Code Initiative
Business Central team members license documentation

Licensing and Pricing on-premises only


Business Central on-premises licensing guide
Business Central on-premises licensing FAQ

Events for partners


Business Central Launch Event: aka.ms/BCLE
Directions NA
Directions EMEA
Directions Asia
Business Central TechDays
Days of Knowledge (Nordic)
Days of Knowledge (Central)
Days of Knowledge (UK)

Events for customers


Business Central Launch Event: aka.ms/BCLE
DynamicsMinds
UG Summit
DynamicsCon
The SMB Opportunity for App Publishers
2/6/2023 • 3 minutes to read • Edit Online

Our mission is to empower every individual and every organization on the planet to achieve more. Particularly,
focusing on those 78 million small and mid-sized businesses (SMB) worldwide that passionately want more
resiliency in their tech intensity and their capability of transforming products and services to face the challenges
in the marketplace. To embrace the constant change and grow, every organization must have a business
application that breaks down the silos of data, processes, and workflow in their operations. This insight enables
employees to respond to daily challenges and opportunities with agility. Market research shows that the
business applications opportunity for software companies in the SMB space is predicted to be 51 billion dollars
by 2025. As a developer, you want to make sure you bet on the winning platform. The BizApps market growth in
this area is 17%; however Dynamics 365 platform growth is increasing at 47%!

Dynamics 365 Business Central


Dynamics 365 Business Central is an all-in-one business management solution that connects operations for
SMBs. It ensures business continuity with a cloud solution that connects sales, service, finance, and operations to
help teams adapt faster and deliver result. Business Central provides app publishers with a modern business
platform that can easily connect to, extend and build on—with little to no code required.

The Microsoft commercial marketplace


Microsoft AppSource is part of Microsoft's commercial marketplace where customers can find, try to get
business solutions apps. It's the launch pad for your joint go-to-market activities with Microsoft and a medium
for business growth. By using launch promotion, demand generation, and joint sales and marketing, your offer
portfolio on AppSource can be the centerpiece of your cloud business engine.
In November 2020, Microsoft AppSource had more than 3 million monthly active users and +20,000 apps.
Specifically, for Business Central, there are more than 1500 apps available and the number is growing fast.

Go-to Market scenarios


As an AppSource publisher, you can focus on the following two scenarios with Business Central and Microsoft
AppSource:
Connect
Add-on
Connect
Connect your existing online service with the Business Central through a powerful API. Following are some
examples of existing connect apps that you can find on AppSource:
Square payments, which allows you take payments with a Square terminal.
Certify which allows users to post expense reports using Certify.com
Scaptify, which connects your Shopify store with Business Central
Learn more about the API to build connect apps: Getting Started Developing Connect Apps
Add-on
You can extend the default capabilities in Business Central to add extra productivity features or industry
functionality to fit the needs of your customer base. The possibilities are plentiful.
In countries, where Business Central isn't localized by Microsoft, you can extend Business Central based on local
requirements to respond to the regulatory or competitive needs of that market.
Here are a few examples of some apps that extend Business Central:
E-Ship and E-Receive from Lanham Associates, which extends warehouse management with barcoding
and labeling, scanning functionality, and interfaces with carriers and weigh scales.
Continia Document Capture, which is an end-to-end solution for document recognition, invoice approval
and digital archiving.
Philippines localization from Pasi, which computes the withholding tax as mandated by the Philippine
government for both customers and vendors.
SwissSalary 365, which is a certified and flexible payroll app that's intuitive and easy to use for the Swiss
market.
Learn more on how to build your app: Get Started with AL

Consultancy services
A large number of business users find it easy to buy consultancy services to research, deploy and manage apps.
Therefore, next to providing Apps, a publisher can also market consultancy services on Microsoft AppSource to
connect with buyers. The offered services could be assessments, briefings, workshops, proof of concepts, and
implementations. In general, the services are typically fixed in scope and duration. They're offered at a fixed price
or free, and have a defined outcome.
Here are a few examples of consultancy services provided by publishers:
Unified Commerce Readiness Intro: 1-Hr Assessment In this 1 hour assessment, LS Retail assesses how a
4-day engagement helps them with implementing their Unified Commerce Cloud solution based on
Microsoft Dynamics 365.
NAV-X Commission Mgt Gold 4-Hr Implementation In this 4 hour implementation workshop, NAV-X
supports the customers in implementing their commission management app.
Learn more about Consultancy Services.

See also
Get Started with Building Apps
Get Started with Building Apps
2/6/2023 • 8 minutes to read • Edit Online

Dynamics 365 Business Central is a business management solution that helps companies connect their services
and operations to streamline business processes, improve customer interactions and make better decisions.
With this modern business platform, you have the convenience to quickly tailor, extend, and build applications
so that they fit your specific needs with little to no code development.
Build a business app for a specific industry, process, or department such as HR, finance, marketing or
operations. Then, publish your app to the Microsoft commercial marketplace, where customers can find your
app, try it and get in touch with you. For more information, see What is the Microsoft commercial marketplace?.
Learn how you can become a Business Central app publisher in six steps in this article.

Step 1: Become a partner


When you become a Microsoft partner, you get access to the Microsoft resources needed to build, market, and
sell your apps. You don't have to be a Microsoft partner to begin developing your apps. But, all of the steps
below are required to gain access to the programs that enable you to publish, market, and sell your apps for
Business Central.
Obtain your work account
Your work account is the email address provided to you by your company. This email is usually in the format
you@yourcompany.com . For more information on work accounts, see Link your work Account.

Join the Microsoft Partner Network


Microsoft Partner Network (MPN) membership unlocks our best resources to differentiate your business, take
your product to market, and sell your solutions. To become a partner, you must join the Microsoft Partner
Network (MPN), at which time you will be assigned an MPN ID. MPN membership is free to all partners; you can
enroll in the MPN here.
Once signed up, you will get an MPN ID – your gateway to access all the membership resources and benefits for
your partnership with Microsoft. There is no cost to obtain a MPN ID as a Network member, and with options to
upgrade to an Action Pack subscription or work toward a competency, you can access even more benefits.
Set up your Partner Center account
Once you have joined the Microsoft Partner Network (MPN), you can set up your Partner Center (PC) account.
The Microsoft Partner Center is a generic portal where partners can sell and manage customer subscriptions for
Microsoft services, such as Microsoft 365, Azure, Dynamics 365, and others, as well as for some third-party
products. For more information, see the Partner Center documentation.
Your Partner Center account provides you with access to pricing information, tools and services, and enables
you to manage admin credentials for your company's work account. Partner Center is also where you can
purchase or renew subscriptions to Microsoft Action Packs, create a business profile to receive and manage
sales leads from Microsoft, and see if you qualify for co-selling opportunities.

Step 2: Register as a publisher


The first step to becoming a publisher is to register in Partner Center (PC). PC is where you submit your apps for
publication, promote them, and manage your offers. To begin the registration process, you must complete these
steps. One of our team members will follow up to help you complete your registration. Once registered, you can
access PC.
For more information, see Partner Center Account.
PartnerSource Business Center (PSBC ) account
To develop apps for Business Central, you're required to be known as a Business Central developer. You must
also have a unique development license file with a specific object range.
To obtain an object range for developing a Business Central app, you must have access to PartnerSource
Business Center (PSBC). Either of the following agreements gives you access to PSBC, which is a first step
towards getting a development license:
An active Partner Registration Agreement (PRA)
A Registered Solution Program Addendum (RSPA)
The relevant contract can be requested through your local Regional Operations Center (ROC) Contracts and
Agreements Team below:
mbscon@microsoft.com if you're based in Europe, the Middle East, or Africa
mbsagree@microsoft.com if you're based in the Americas
mbslques@microsoft.com if you're based in the Asia Pacific region.

Step 3: Your unique app specifications


Requesting an object range
When you develop an app for Business Central, you must request access to an object range that holds some
objects for your solution. To avoid overlap between objects used in different solutions, each partner is assigned
many objects in a unique object range. For example, a partner is assigned the object range 70,001,000 –
70,001,999. The object range gives them 1000 numbered objects that they can use to develop Business Central
solutions.
Depending on where you'll deploy your Business Central solution, online or on-premises, you can use different
licensing methods and object ranges.
There are currently two available ranges that you can request. Both have some characteristics to keep in mind:
RSP Object Range (ID range 1,000,000-69,999,999)
This object range is tied to the RSP Program details.

IMPORTANT
We currently advise new publishers to not request an RSP object range

App Object Range (ID range 70,000,000-74,999,999)


This object range was originally designed just for apps in the Microsoft commercial marketplace to be
used in Business Central online.

IMPORTANT
We currently advise new publishers to request an app object range.

Currently, you can implement apps developed in both the RSP range and the app object range in Business
Central online and on-premises, as well as partner-hosted.
You can request an object range by downloading the object range request form here. After completion, send
them to your Regional Operational Center (ROC) for processing:
mbscon@microsoft.com if you're based in Europe, the Middle East, or Africa
mbsagree@microsoft.com if you're based in the Americas
mbslques@microsoft.com if you're based in the Asia Pacific region.
Downloading your development license file
After your Regional Operational Center has processed your Agreements and Object Range Request forms,
download your company's unique developer license from PartnerSource Business Center. Find it in the license
key configuration section under the developer tools section.
Register your unique prefix or suffix
In your extension, the name of each object must contain a prefix or suffix that is registered for your publisher
name. For more information about the use of affixes and the registration process, see Benefits and Guidelines
for using a Prefix or Suffix.

Step 4: Getting access to preview bits


Get access to preview builds by joining Microsoft Collaborate.
In Microsoft Collaborate, you get access to a set of Business Central builds:
The current major version
An upcoming major version
Daily builds
You must have the following prerequisites to register on Microsoft Collaborate:
Azure Active Directory (Azure AD).

NOTE
If you have Microsoft 365, then your company most likely has Azure AD.

Azure AD Global Administrator permission

NOTE
To find out if your company has an Azure AD account, check with your system administrator.

Step 4 A: How your Global Administrator must register for Collaborate


Only your company's Global Administrator can start the onboarding to Collaborate. They must register
at https://aka.ms/Collaborate, choose the Get Star ted action, and then complete the registration form.
The administrator can then add the relevant colleagues.
Optional Step: Add your coworkers to Microsoft Collaborate
To add coworkers:
1. Sign in to Microsoft Collaborate with your Global Administrator account at aka.ms/Collaborate.

2. Choose the settings icon in the top-right corner of the page, got to on account settings, and choose
user management .
3. Choose the grey ADD USERS button, and leave the default choice to Add existing users as-is. Now,
you can search for the user(s) that you want to add to Collaborate. To add them, you need to choose them
from the menu, and then choose the grey ADD SELECTED button.
4. You've successfully added your coworkers to Collaborate. Users can now sign in to Microsoft Collaborate
using the following link: aka.ms/Collaborate
Step 4 B: Getting access to the available builds and engagements
Once you've successfully registered on Microsoft Collaborate, Microsoft must assign you to the right programs,
and engagements before you can see the preview bits. Contact Dyn365BEP@microsoft.com and provide them
with information about the relevant users. the following table illustrates the type of information that you must
submit:

P UB L ISH ER DISP L AY W O RK A C C O UN T
NAME M P N ID F IRST N A M E L A ST N A M E EM A IL

Contoso 12345 Eugenia Lopez Eugenia.Lopez@Cont


oso.com

Contoso 12345 Quincy Watson Quincy.Watson@Con


toso.com

After sending the email, expect a response from Microsoft within 1-2 business days.

Step 5: Resources while you develop your solution


Find below some guiding resources on how to develop your apps for Business Central.
Microsoft Learn
Learn new skills and discover the power of Microsoft products with step-by-step guidance. Start your
journey today by exploring our learning paths and modules.
Microsoft Docs
Find The developer and administration content on Microsoft Docs
Join the conversation
In the dedicated Yammer network, join the conversation on developing apps
Join the monthly Office hour calls
Join the monthly Office hour calls to learn more about a hot topic.
Get coaching from experts
Need help with developing your apps? There's a community of ISV Development Centers specialized in
Business Central ready to engage with you.
Set up DevOps processes for your project
It's recommended that all partners set up DevOps processes to ensure that this validation process happens
automatically and regularly.
You can find resources for how to set up full plug-and-play DevOps processes using AL-Go for GitHub:
https://aka.ms/AL-Go.
Step 6: Publish your app in the Microsoft commercial marketplace
Once your app is ready for submission, you can list your app in the Microsoft commercial marketplace by
submitting it in Partner Center. For more information, see Create a Dynamics 365 Business Central offer.
Before you submit, we recommend that you review the technical validation checklist and marketing validation
checklist. The two articles list all requirements that you must meet before you submit an app for validation.
If you don't meet these mandatory requirements, your extension will fail validation

See also
The SMB Opportunity for App Publishers
The Lifecycle of Apps and Extensions for Business Central
Update Lifecycle for AppSource Apps FAQ
Maintain AppSource Apps and Per-Tenant Extensions in Business Central Online
Microsoft Responsibilities for Apps on Business Central online
Customize Business Central
2/6/2023 • 2 minutes to read • Edit Online

Every business is unique. Dynamics 365 Business Central us ready to adapt to how customers work: their
streamlined processes, their terminology, and how their employees or departments connect and collaborate.
Whilst there may already be add-on apps available on AppSource that cover a customer’s need, we also have
the tools for you to build fully custom functionality or adapt what is already available out-of-the box.

Examples of custom changes to Dynamics 365 Business Central


Capture industry-specific information about products and services.
Connect to other in-house data repositories or legacy systems to reduce duplicate data entry.
Hide data fields that are rarely or never used.
Add a printable report covering legally required declarations for a specific industry.
Create a role-specific dashboard and set of tasks for a unique organizational role, such as mobile purchasing
managers, or recruiting specialists.

How do I customize?
For most simple changes to the user interface, the browser-based Designer allows you to rapidly adjust the UI
for all users within the organization, without needing to write any code. Similar tools are available to customize
the UI for an individual user, or users of a specific role. Hide columns that aren't needed, drag-and-drop to
reposition FactBoxes, bookmark links to commonly used lists, or show data fields that were previously hidden:
these are all examples of simple changes that can be rolled out to an entire organization using Designer. For
more information, see Using Designer
With Visual Studio Code and the AL Language extension, you’re able to customize existing pages and tables by
creating page and table extensions, or you can add new tables and pages to implement entirely new
functionality. You can even write business logic in AL. For more information, see Get Started with AL.
You can start customizing in either Designer or in Visual Studio Code. If you start in Designer, the AL source code
generated by the Designer is downloadable, so you can continue developing in Visual Studio Code if needed. If
you start developing in Visual Studio Code, you'll initiate Designer directly from Visual Studio Code, to continue
customizing the UI with a more visual and real-time overview of your changes. When done using Designer you
synchronize changes back to Visual Studio code keeping all changes reflected in the AL source code.
The resulting AL code is compiled into an .app file, which can be deployed to production environments or other
sandbox environments for testing.

How do I test my custom changes?


To ensure business continuity and protect the integrity of live customer data, you can't customize Dynamics 365
Business Central for an organization running in production. Instead, test your custom changes on hosted
sandbox environments or in Docker containers. Changes can be tested thoroughly in the browser by developers
or even end-users until they're deemed fit to deploy into production where they're applied as an app and can
immediately be enjoyed by everyone in the organization.

Where do I learn more?


To learn more about customization, select the following links:
Using Designer
Get Started with AL
AL Development Environment
Update Lifecycle for Customizations of Business Central Online
Maintain AppSource Apps and Per-Tenant Extensions in Business Central Online
Business Central Learning Catalog
The Lifecycle of Apps and Extensions for Business
Central
2/6/2023 • 6 minutes to read • Edit Online

When you build an app or extension to Business Central and get that published to AppSource, it becomes an
app like so many others - the app itself can be updated, and the platform that it sits on, Business Central online
itself, will also get updated. But what happens after your app gets published?
When your app has passed all of our validations and has gone live to AppSource, customers can install your
extension and use it for their business. But you are expected to keep it compliant with the service and update it if
something changes.
The following sections describe the different upgrade scenarios that we have seen play out as we update
Business Central. For more information about your responsibility for keeping your app updated and the
resources that are available to you, see Maintain AppSource Apps and Per-Tenant Extensions.

Scenario 1: Business Central service update


You don't need to make any bug fixes, feature adds, or app changes to your app. It continues to work fine
without any interaction on your part.
Impact of service updates
The monthly service upgrades to Business Central do not impact your app. Your app just gets moved along and
no upgrade code from your app needs to get used. Business Central itself gets upgraded on your tenant, and
once complete, the customer sees no difference with your app.

Scenario 2: App update


You (our partner) add some features to your app and also some minor bug fixes. The app is submitted for
validation. The app passes validation and gets checked into the service. This is now the active app for any new
tenants and also for existing tenants that have never had your app installed before
Impact of app updates
Customers can either do an uninstall and then reinstall on their own, or they can ask their partner do it on their
behalf from the Extension Management window within Business Central. Otherwise, they would have to wait
until our every 6-month major release. That is the only time we do a force upgrade of extensions (except for
critical bug hotfix extension updates)

Scenario 3: Reported bugs in your app


You (our partner) has various customers report some bugs that are impacting their usage of the app. The bugs
aren't critical but they are important. The partner makes the fixes in the app and resubmits for validation. The
app passes validation and gets checked into the service. This is now the active app for any new tenants and also
for existing tenants that have never had your app installed before
Impact of bugs
We still do not force the upgrade of this app to this latest version on all of the tenants. Some tenants may not be
using the functionality that includes this bug and continue to work fine on the current version of the app.
Therefore, you should work directly with all of the impacted customer tenants to uninstall and reinstall to get the
latest app version that contains fixes for the bug.
Scenario 4: Critical bug in your app
If a bug which leads to core functionality being broken or data loss/corruption/misrepresentation is found in the
application, and the issue prevents customers from performing time-critical tasks, the validation and
deployment of the application can be prioritized. The partner must create a support ticket for this case and they
must immediately provide a fixed app for validation through Partner Center. The validation team makes this a
top priority and does validation as soon as possible. If the fixed application passes validation, it will be checked
into the service and will become available for environment administrators to install.

Scenario 5: Microsoft feature breaks your app


Microsoft has to break your app file for a needed Business Central core change. Some reasons for breaking
could be security, bugs in the underlying code, high priority feature adds, and so on. Keep in mind, we do our
very best to not break your app through our changes. We try and find proper ways of doing the changes
without breaking your app. However, if we can't find a proper (non-breaking) way, then we could break your
app. This won't be as likely in a minor update release (unless a security change is required on our part and that
is the change that breaks you), but it can be more likely in our major (every 6-month) releases.
Impact of breaking changes
Here is our process when this takes place:
First of all, Microsoft will not make a breaking change in the production environment at any point. Therefore,
existing tenants are not expected to see this breaking change occur.
When we make a breaking change, we do it in a build branch that is for a future release (monthly service
minor or major release)
We notify the partner in advance and give the partner ample time to fix their app, get it validated, and have it
ready
The fixed app will already be in our service and slotted as required for when your tenant is to be moved to
the Business Central release that has the app breaking change
As a result, the customer (tenant owner) should never see their Business Central break. Because the tenant
gets moved from one monthly service update of Business Central to another, the tenant is being upgraded to
the release of ours that breaks the specific app. However, our service detects that there is a new required
version of that app (your fixed version). Therefore, we auto install the fixed version of the app for the tenant

Conclusions
You're responsible for your app. You own the process of updating the app and providing upgrade code if the
schema changes between versions of the app.
If a customer uninstalls your app, and then installs it again later, then when they install the app the second time,
they get the latest version from AppSource.
How Microsoft handles your app
When Microsoft upgrades a tenant with a service update, your app is tested against the new service version. If
the app breaks, Microsoft rolls back to the previous healthy state. Your customer never learns that anything was
about to break.
When a tenant uninstalls and reinstalls an extension via the Extension Management page or AppSource, there is
platform logic that determines whether an Install or an Upgrade must take place. We detect which version of the
extension the tenant previously had installed and perform the appropriate action. Therefore, the result of
manually uninstalling/installing the extension is the exact same as an automated upgrade.
Additionally, there will not be any data loss during uninstall, install, or upgrade actions. Data for extensions is
stored in its own tables in the tenant database. Before an extension gets installed, it first get synchronized on the
tenant database. This step is implicit and happens automatically when a tenant installs an extension. This
synchronization process creates the database tables for the extension. Once the extension is installed and the
tenant is using it, extension-specific data will get stored in these tables.
When an extensions gets uninstalled, these tables do not get removed. Therefore, when the extension gets
reinstalled (or upgraded), the data is still available. You do not need to worry about data loss for choosing the
uninstall/install route. However, do keep in mind that if any actions are being performed on the tenant while the
extension is uninstalled, the extension's events and such will not be firing, and your app may miss the creation of
new data. Try to perform the uninstall/install while the tenant is not online.
For more information, see When apps or PTEs cannot be updated by Microsoft.

See Also
Publishing and Installing an Extension
Retaining table data after publishing
Upgrading Extensions
Add your App to AppSource
Checklist for Submitting Your App
Upgrading AppSource Apps in Production
Maintain AppSource Apps and Per-Tenant Extensions
Update Lifecycle for Customizations of Business
Central Online
2/6/2023 • 2 minutes to read • Edit Online

When you create a tenant-specific customization, or an extension that is scoped to a single Business Central
environment (often referred to as per-tenant extensions), you must take the lifecycle of the extension into
consideration. For more information about the extension lifecycle and events that can cause incompatibilities
between the extension and base application, see The Lifecycle of Apps and Extensions for Business Central.
You are responsible for your extension. You own the process of updating the extension and providing upgrade
code if the schema changes between versions of the Business Central base application. When an update is
available for your Business Central environment, all extensions, both AppSource extensions and tenant
customizations, must be compatible with the next version of the base application before the update can be
installed on the environment. You are responsible for ensuring that your extensions are compatible with the
update version.
In this article, we describe the process for ensuring update compatibility for tenant customizations.

Automated Extension Validation


An automated service validates all tenant customizations before an update is marked for a scheduled update of
an environment. This validation compares the extension's dependencies with the updated version of the
Business Central application to see if any changes caused incompatibilities with the new version.
If the validation service discovers any tenant customizations that are not compatible with the update, an email
notification is sent to the tenant administrators listed on the Notification recipients tab of the Business
Central administration center. For more information, see Managing Tenant Notifications.

IMPORTANT
At least one email address must be specified as a notification recipient to receive the update notifications. If you do not
speciy an email address, you will not be notified of updates and other changes to the tenant.

The email notification provides information on the incompatible extension, detail on which properties must be
updated, and steps to bring the extension into compatibility.

Update Failure Notification


If a Business Central environment has an extension that is not compatible with the update version, the update
cannot be applied. If an update fails due to an incompatible extension, a notification is sent to the tenant
administrators listed on the Notification recipients tab of the Business Central administration center.
The notification is similar to that provided by the automated extension validation. It provides information on the
incompatible extension, detail on which properties must be updated, and steps to bring the extension into
compatibility.

Automatic Extension Removal


The publisher of an extension must maintain compatibility with the new release of Business Central. An
extension that is not compatible with the update within 90 days of the first notification of incompatibility will be
removed, and then the environment will be updated.

See Also
Retaining table data after publishing
Upgrading Extensions
Updating Environments
Maintain AppSource Apps and Per-Tenant
Extensions in Business Central Online
2/6/2023 • 8 minutes to read • Edit Online

As a partner, keeping your apps and per-tenant extensions (PTEs) up to date is your responsibility. Business
Central is regularly updated with major and minor releases. These updates provide customers with a business
application that is always compliant, secure, and enriched with new platform and application functionality. Often
customers choose Business Central because of this promise of having an always up-to-date business solution.
To not break this promise, developers that bring apps to Microsoft AppSource, and resellers that provide PTEs to
respond to the unique needs of customers, have a responsibility to align their code to the Microsoft release
rhythm.
The following diagram illustrates the time for how updates roll out for Business Central online and how you can
use previews to test your apps ahead of time:

An inability for Microsoft to update tenants because of publishers incompatible code causes serious disruption
in the service and must be avoided since it impacts the trustworthiness of the service and customer satisfaction.

Resources
To help app publishers keep up with their update responsibilities, Microsoft provides the following resources:
Release plans about what's new and planned
For more information, see Dynamics 365 release plans.
Access to pre-release bits
Business Central partners have access to the next major, next minor, and daily pre-release bits in Docker
through Microsoft Collaborate. To get access to Collaborate, follow steps 1 and 4 in the
https://aka.ms/bcpublisher article. Use the pre-release bits to test apps against upcoming updates.
Learn about the update lifecycle for apps and extensions and automated extension validation. Use the
AppSourceCop analyzer rules to keep your code compliant. Get agile with AL Go for GitHub and stay on
top of changes that way.
Information about what will be deprecated
With all Business Central releases, Microsoft controls and regulates breaking changes with major releases
and communicates upcoming breaking changes at least one year in advance. If developers missed this
above info, the compiler in Visual Studio Code also warns for potential controls that will become obsolete
in future versions and how to deal with them. Use the analyzers actively to make sure your code is ready
for the next update.
Policy definitions and terms
The publisher agreement and the commercial marketplace certification policies describe the
responsibilities of app providers for how to publish and maintain apps in the Microsoft monthly rhythm.
When a PTE gets installed, the publisher also agrees to the terms to keep that code current and updatable.
Training and coaching
Microsoft provides a set of tools, training, and documentation to help partners find the info they need to
keep up with these responsibilities on continuous integration and continuous deployment. External
providers, including ISV Development Centers, MasterVARs, and training centers, can provide in-person
training and coaching.
Service notifications
Business Central online will support app and PTE publishers with extra warnings about potential technical
incompatibility. If publishers respond to these notifications in due timing and avoid incompatibilities
repeatedly, Microsoft will stand with these publishers to help where needed. If a publisher includes a
telemetry key in their app, then, starting with 2020 release wave 2, Business Central also provides
publishers with telemetry about upgrade failures that happen in production because of issues in the
publisher's upgrade code.
If publishers lack to keep their code updatable, they risk that ultimately their apps or PTEs will be removed from
the customer's tenant, and this will most likely result in important data not being captured as it should. For apps,
this also means removal from the marketplace.
Since resellers are the first line contact point for customers, they carry responsibility to explain what it means to
load code in a customer's environment. The best way is to explain this is with terms.
We advise these terms include topics like intellectual property rights, upgrade responsibilities, associated costs
to keep code updatable, support options, data privacy, and so on.

Pre-release publisher support to keep apps and PTEs compatible and


up-to date
Publishers have several tools available for them to keep their code in good shape. Not least, a Public Preview
release is made available approximately one month before the announced release date for a major release. In
that Public Preview release time frame, Business Central will automatically test and notify publishers of existing
apps and PTEs running in production on technical incompatibility with the upcoming release.

IMPORTANT
Microsoft tests code based on technical compatibility. As the publisher, you are still responsible for all functional and
logical validation. For more information, see The Lifecycle of Apps and Extensions for Business Central.

NOTE
If an app has been published through AppSource, it should not be tested, installed, or in other ways treated as a PTE since
this will create conflicts.

When apps or PTEs cannot be updated by Microsoft


This section describes the processes that are initiated during and after upgrade attempts of code provided by
publishers of apps or PTEs. For information about handling a PTE that has conflicts with another extension, see
Upgrading Per-Tenant Extensions that Conflicts with Other Extensions.
T+1 – T+30 : Microsoft alerts administrators, resellers, and ISVs
Shortly after a service update of Business Central online (Day T ), Microsoft will initiate daily updates
attempts on all tenants. In these update attempts, the publisher's provided upgrade code is triggered and
run. These attempts run repeatedly in a time frame of approximately one month until the upgrade is
successful. For more information, see Major Updates of Business Central Online.
With every unsuccessful upgrade attempt, stakeholders will receive notifications. Customers and their
reselling partners can follow these notifications in the Business Central administration center.
ISVs who provide third-party AppSource apps might not be listed in the customer's admin center. The
reseller will in most cases have worked with the ISV to test compatibility, but after two weeks (Day T+15 )
of failed upgrade attempts, the Microsoft AppSource team will also send the app provider a warning
message that action within the next few days is required. Incompatible extensions can be uninstalled
within 14 days if they prevent deployment of security updates.
This message will explain that if they fail to respond correctly, their app will be removed from AppSource
at Day T+30 .
T+30 – T+60 : Microsoft alerts the customer
After one month of failed upgrade attempts (Day T+30 ), the customers will be notified again that apps or
PTEs are incompatible with the new version of Business Central, and that no further automatic upgrade
attempts will be planned until further notice. Although the publisher's code continues to run on an
outdated version of Business Central online, the customer must work with their reseller to resolve these
issues immediately so that the tenant can be updated. Next to messages in the Business Central
administration center, all users in the customer's tenant will also get more active warning about the
incompatibilities when they use the product in the browser or their mobile device.
For AppSource apps, if no appropriate action or follow-up was taken by the publisher since the release (T
- T+30days ), the app will be removed from AppSource. This means no new customer will be able to
install the app in a new tenant. The main reason for removing an app from the marketplace is to ensure
that no new customers will be affected by incompatibilities with the latest version of the base product,
Business Central.
If the publisher wants to have their app available again, they must mitigate all existing incompatibility
issues and go through the full validation process again.
If the source of the incompatibility has been resolved by the publisher, they'll have to submit a support
request to schedule a new set of upgrade attempts for any tenants that are blocked because of this
incompatibility. They'll also have to work with their resellers to inform them about the compatibility
resolution.
T+60 – T+150 : Microsoft initiates the customer wind-down period
If the incompatibility issues are not resolved at T+60 , and the publisher remained unresponsive to the
request to resolve the incompatibility, Microsoft may choose to send out a wind-down communication to
the customer about removal of the publisher's code.
This communication will share that the code from the publisher will be removed in 90 days from the day
of the communication from Microsoft (T+150 ).
During this wind-down time, the customer and their reselling partner are fully responsible for finding a
solution on how to proceed in this situation. If the customer decides to leave Business Central, or decides
to use another publisher, they can access their data by exporting the database, use RapidStart Services, or
copy data to Excel. For more information, see Exporting Your Business Data to Excel in the business
functionality content.
Microsoft may also choose to remove all existing apps by this publisher from AppSource and block the
publisher from publishing new apps for Business Central.
If this wind-down period is initiated, and the customer was able to fix the incompatible issues with their
reseller and potential publishers, it will be at Microsoft discretion if the publisher's code will be removed
from Business Central or not.

Get notified about incompatibilities by Microsoft


It is crucial for you to keep contact details correctly up to date. We advise you to use global team aliases instead
of individual mail addresses. Here are the mail addresses that we'll use in the process that is described in the
When apps or PTEs cannot be updated by Microsoft section:
PTE publishers
The mail addresses specified in the Business Central administration center; this could be both a customer
user and a partner user.
App publishers
The mail addresses specified during App publication in the partner center during app publication as
support and engineering contact details.
Customers
The mail addresses specified in the Business Central administration center; this could be both a customer
and a partner user.

See also
The Lifecycle of Apps and Extensions
Update Lifecycle for Customizations
Microsoft Responsibilities for Apps on Business Central online
Technical Support for Business Central online
Sending Extension Telemetry to Azure Application Insights
Major Updates and Minor Updates for Business Central Online
Discontinuing an AppSource app
2/6/2023 • 2 minutes to read • Edit Online

The following section describes the process that we recommend AppSource partners follow to remove an app
from the AppSource marketplace.

Update the AppSource listing


Update the AppSource listing to inform potential customers that the app should not be installed and that it will
not be maintained in the future. The AppSource listing should still remain available to allow you to deploy bug
fixes for your existing customers, but also to allow your existing customers to reinstall the app if they have
uninstalled it by accident as their business might depend on it.

NOTE
As the offer can still be installed by new customers, we recommend switching the listing type to 'Contact Me' in order for
you to control who is installing the app, see Listing Types. You can also define custom logic within your app to define who
is allowed to install it.

Notify existing customers (T+1 to T+60)


Notify existing customers through the channels that you consider most appropriate about the fact that the app
has been deprecated (day T ) and that it will removed from the marketplace. If possible, you should recommend
alternatives that the customer can use to fulfill the same business scenarios.

Remove the AppSource listing (T+150)


Remove the listing from AppSource by using the Stop selling option in the Partner Center portal. It is your
responsibility to maintain the app for the entire period until you click Stop selling . You can find more
information here Update existing offers in the commercial marketplace.
You can optionally delete the offer from the Partner Center portal.

FAQ
Do I have to uninstall the app for every tenant?
No. It is the responsibility of the partner maintaining the environment to uninstall the app when they see fit.
Does the customer receive any kind of notification?
The customer does not receive any notification from Business Central about the fact that the offer has been
deprecated. It is your responsability to reach out to your customers. If at some point, the app blocks the upgrade
of the environment, then the partner maintaining the environment will be notified that the app is blocking
upgrade. The partner maintaining the environment, can then decide at that point to uninstall it or to contact you
for additional information. For more information, see Maintain AppSource Apps and Per-Tenant Extensions in
Business Central Online.

Does the app get automatically uninstalled from customer


environments?
The app will not be automatically uninstalled from customer environments. If the app blocks the upgrade of the
environment and the partner maintaining the environment has not unblocked the upgrade by uninstalling the
app, the app will be uninstalled automatically. For more information, see Maintain AppSource Apps and Per-
Tenant Extensions in Business Central Online.
Are the apps completely removed from Business Central?
Even after you removed your offer from the AppSource marketplace, the apps are still stored in Business Central
because there can still be customers using them.

See Also
The Lifecycle of Apps and Extensions for Business Central
Maintain AppSource Apps and Per-Tenant Extensions in Business Central Online
App Identity
Development of a Localization Solution
2/6/2023 • 5 minutes to read • Edit Online

If you want to bring the capabilities of the Dynamics 365 Business Central to your local market, then there are
several reasons why you would want to choose Dynamics 365 Business Central:
Easy to translate and strong base capabilities ready for localization.
Reach more customers by showcasing your localization apps on Microsoft AppSource.
Dynamics 365 Business Central provides a proven ERP platform and application for your localization apps,
which adapts functional areas to the requirements of the local market.
Localization apps are simply apps for Dynamics 365 Business Central - learn more about getting onboarded as
an app publisher here: Get Started with Building Apps.

Localization apps functionality


Localization apps contain a set of functionalities addressing local requirements that fall within one of the
categories below. Make sure to split up your localization apps at minimum according to these categories:
Regulator y requirements - local functionality that helps businesses fulfill their legal requirements, such as
tax reporting, local GAAP, and other regulatory requirements.
National standards requirement – local functionality that addresses local standards, such as banking and
payment formats, address formats, or local interpretations of global standards.
Market requirements - nice-to-have, competitive requirements – local functionality beneficial to the
productivity business processes in a country and thereby adding value to business but aren't required from a
regulatory perspective.

Service availability in other countries


Follow this page for information about planned country and regional expansions of Dynamics 365 Business
Central.

Product scope for localization apps


Apart from fulfilling the technical checklist for your app, the minimum viable product scope for localization app
is:
Local Regulatory Features.
Tests for Local Regulatory Features.
Upgrade code for localization apps.
Set up data RapidStart package for the localization app.
Translation of a localization app to local language(s) and base app if you're the first partner enabling
localization for the country (Learn more about Dynamics Translation Services).
Translation of the localization app's documentation. For more information, see Translate the Help and
Translate documentation files.
National Standard Features (local part) are recommended to be built as an app – separate from the
localization app.
Market Required and Local Competitive Features are recommended to be built as an app – separate from the
localization app.
Using .NET assemblies in your localization app will fail in the technical validation of an app. Instead,
contribute to C/AL Open Library GitHub repository with requests you have for .NET.
It's recommended to logically break down the full local functionality set, at a minimum within the above
categories. This approach provides optimal flexibility for customers to choose what they really need in terms
of local functionality. And it makes sure that critical pieces of local functionality don't break upgrade
processes nor are upgrade heavy.
Most customers in the local market will need most of the local regulatory features. In the category of local
regulatory features there will be some features that, even though they're legally required, apply to
companies of a certain size, revenue threshold etc. Such situations are opportunities to further logically
breakdown localization apps into smaller focused-functionality sets.
Consider separating localization functionality by the frequency of changes to smaller localization apps. If for
example, your local feature contains one part that is stable and one part that is frequently changed based on
regulation changes, make sure to keep the stable part as one app and the changing part a separate
localization app. This approach ensures better test coverage, faster response to changes and fewer upgrade
issues.
Use worldwide frameworks available in Dynamics 365 Business Central (W1) when building features for,
such as VAT reports, banking formats, data exchange, and others where most functionality is common to all
countries but there are some local rules or business formats that are extensions of global frameworks or
formats. Make sure to familiarize yourself with such frameworks to reduce effort, reuse code, and properly
utilize extensibility points and integration events. If you notice opportunities for improvements in such
frameworks or missing extensibility points, make sure to contact us to work together in improving this.
Consider rethinking local reports by categorizing the reports that you want to include in your localization
app(s) in following categories: reports printing lists could be converted to list pages and offer more
functionality using Excel add-in, reports providing insights or aggregating data could be converted to Power
BI reports and dashboards, frequently customized reports (local document reports like invoices, credit
memos...) could utilize Word document layouts so customer's power users can easily customize them, for all
others fall back to RDLC reports
Prepare a setup data RapidStart package for the production company and translate to local language(s).
Consider preparing a local demo data RapidStart package for the evaluation company and translate it to local
language(s).
Prepare setup guides (wizards) for areas that are complex to set up to help users enable, discover and have a
good first experience using your localization app.
Fork the Dynamics 365 Business Central documentation from public GitHub repository. Such an approach to
documentation can help when other partners or ISVs take dependency on your localization app. For more
information, see Configuring the Help Experience.
Consider converting field-based documentation to task-based documentation using tooltips and Dynamics
365 Business Central documentation GitHub repository. Rulesets can help you ensure, for example, that no
fields or actions are missing tooltips.
If your localization app(s) are extending Business Central data model with new tables and/or fields, you must
set the DataClassification property correctly. Localization apps with fields having the DataClassification
property set to ToBeClassified will be rejected. Read more on Classifying Data in Business Central here.
If you're converting an existing localization (developed in C/AL) to localization apps (check this video(requires
PartnerSource access)), as described in technical checklist for your app, you'll need to set the ApplicationArea
property on UI elements that you want to make visible in Business Central. To help you with that use
NAVApplicationAreaHelper PowerShell command let to do this in bulk.
NOTE
You can also create an integration if you find it beneficial to have some functionality placed outside the Dynamics 365
Business Central environment and instead connect to Dynamics 365 Business Central using for example APIs or Web
services.

NOTE
If you have questions for building localization apps, please contact the Microsoft localization team.

See Also
Get Started with Building Apps
The SMB Opportunity for App Publishers
Get Started as a Reseller of Business Central Online
Countries and Translations Supported
Business Central Learning Catalog
Microsoft Responsibilities for Apps on Business
Central online
2/6/2023 • 2 minutes to read • Edit Online

Business Central online is a cloud service for small to medium-sized businesses that is built on and for Microsoft
Azure. Business Central brings together the business management solution, business intelligence, infrastructure,
computing, and database services in a single offering that enables organizations to run horizontal or industry-
specific apps from Independent Software Vendors (ISVs), without the hassle of managing infrastructure.
The Business Central online model distinguishes specific roles and responsibilities for partner-provided vertical
solutions, system integrators, resellers, and Microsoft throughout the life cycle of the service. Microsoft
maintains the Business Central service by deploying, actively monitoring, and servicing the customers'
production tenants that are running on the service. This includes allocating the required system infrastructure to
run the service and proactively communicating to customers about the service's health (which is done through
the Service Health dashboard in the Microsoft 365 Admin Portal).
Microsoft responsibilities in the Business Central online service include:

A REA RESP O N SIB IL IT IES

Infrastructure Storage and database capacity management


High availability and disaster recovery
Platform security and compliance
Infrastructure capacity, scaling in response to
demand
Infrastructure management and deployment
Data center networking, power, and cooling

Base application and platform Availability and security


Diagnostics, patches, updates, hotfixes, and updates
Monitoring and first-line support for partners
building apps

Lifecyle Services portal (EmbedApp program) Development, deployment, and support of the portal
functionality
High availability and disaster recovery
Monitoring, updating and patching
First-line support for partners

See Also
Get Started as a Reseller of Business Central Online
Maintain AppSource Apps and Per-Tenant Extensions in Business Central Online
Administration of Business Central Online
Technical Support for Dynamics 365 Business Central
Components and Capabilities
2/6/2023 • 2 minutes to read • Edit Online

When you build an app for Business Central, be it an AppSource app or an Embed App, you must be aware of
which components and deployment steps are provided by Microsoft and which you must provide.

Components
Base application
The base application is the Business Central application provided by Microsoft, customized and extended to fit
the needs of a market segment that an app wants to serve. Major releases and cumulative updates (CUs) of the
base application are publicly available on Microsoft Download and as artifacts for use with Docker.
Pre-released versions of the base application are available as artifacts for participants of the “Ready and Go”
program via Microsoft Collaborate for use with Docker. Although we recommend always using the latest version
of the base application, partners can choose any version they need. The only requirement is that the partner
makes sure that the base application version that they base their app on is available in Business Central online
production environments.
AppSource apps must specify the dependency of a specific base application in the settings for their app. In
contrast, the base application is an optional part of an Embed App package. If the partner has implemented all
required functionality in their library extensions, they do not have to include the base application itself with the
Embed App. Instead they should specify, in the metadata of the Embed App, which version of the Business
Central base application they are targeting, just like an AppSource app.
Microsoft recommends all partners to move towards a model where the code-customization of the base
application is not used. Keep track of new capabilities in the base application and platform in the release plans.
Platform
Partners who build apps for Business Central online must make sure that it is compatible with a supported
version of Business Central platform.
The Microsoft platform is updated in the following way:
Minor updates
Microsoft will ship minor platform updates monthly and major platform updates every six months.
Minor updates can include bug fixes and improvements which should not affect the compatibility of the
platform with the previous version of the application. In rare situations, partners may be asked to
recompile their solution to work with a minor update of a Business Central platform.
Major updates
Major updates will include changes that can require partners to perform a technical upgrade to make
their application work with the new version of the platform. For more information, see the Dynamics 365
release plans

Ecosystem
Business Central online is part of a rich ecosystem of other Microsoft and 3rd party services, which partners and
customers can decide to take advantage of.
The following integration capabilities of the Business Central can be considered:
IN T EGRAT IO N C A PA B IL IT Y STAT US

Dynamics 365 API endpoint Available if the base application objects are unchanged

Outlook Add-in Available

Power BI Available if the customer has a Power BI license

Power Automate Available if the customer has a Power Automate license

Power Apps Available

Microsoft 1st party integration apps included with Business Available, but in many cases the partner must set up a
Central (Yodlee, Quick Books, OCR, AMC, and others) separate agreement with these service providers

Azure machine learning Available if the partner has an Azure ML subscription

Integration with Dynamics 365 Sales Available

Microsoft Graph Currently under evaluation

See Also
Microsoft Responsibilities
Embed App Overview
Add your App to AppSource
2/6/2023 • 2 minutes to read • Edit Online

AppSource is a market place where partners can provide marketing details, such as descriptions, whitepapers, or
videos about their app for Business Central.
Embed App partners can choose to promote themselves and their Embed App on AppSource.

IMPORTANT
Unlike all other apps, solutions that are part of the Embed App program are not uploaded to AppSource itself. Instead,
the app package is uploaded, deployed and tested via Lifecycle Services. AppSource in this case is used for the marketing
purposes, not as a repository of Apps.
All other apps do submit their app to App Source. For more information, see Technical Validation Checklist and Marketing
Validation Checklist.

IMPORTANT
As soon as your app has been uploaded to the AppSource marketplace, it will be used as a baseline during the technical
validation of your next submission(s). As a consequence, you won't be allowed to perform breaking changes without
obsoleting the AL objects first and you won't be allowed to perform schema breaking changes; breaking changes on
tables or table extensions. This applies also if your extension isn't used by customers yet. You should then not submit your
app to the AppSource marketplace if you are still developing it and expect to change it in the near future.

See Also
Get Started as a Reseller of Business Central Online
Build Your Business on Dynamics 365 Business Central
Marketing Validation Checklist
Technical Validation Checklist
Embed App Overview
Marketing Validation Checklist
2/6/2023 • 3 minutes to read • Edit Online

The storefront details on AppSource are the first impression that prospects get regarding your offer. First
impressions last, so make sure to invest some time in developing the content on the storefront, so it gives a
good impression from the beginning. Failing to do so will jeopardize the hard work you put in, when developing
your offer, likely leaving the prospect confused or looking elsewhere. Accordingly, we recommend you put in the
time, effort and due diligence when developing this content.
You use Partner Center to submit your offer to AppSource. In the following, you can find information on all the
marketing-related items that you need to fill out in Partner Center prior to submitting your app to AppSource.
Follow this marketing validation checklist and get your app passed on the first submission.

What do I need to know before I begin?


You need to have the following three items in mind, when you're creating your storefront and marketing
material.

IT EM REQ UIREM EN T DETA IL S

Branding Make sure to read the branding Read more


guidelines carefully before you start
referencing the product name.

Language Discover what to consider for each Read more


storefront detail when it comes to
language.

Microsoft images Make sure not to use any Microsoft Read more
images (for example, the Business
Central icon or Dynamics 365 logo).

How do I fill out the marketing section in Partner Center?


The following section walks you through the marketing-related components, that is, offer setup, properties, offer
listing, and availability, which you need to fill out in Partner Center prior to submitting your app to AppSource.
Offer Setup
IT EM REQ UIREM EN T DETA IL S

App type Read more about the types of apps Read more
you can submit to AppSource.

Listing type How do you want potential customers Read more


to interact with your offer?

Customer leads Provide connection details to the CRM Read more


system where you would like to send
customer leads.

Properties
IT EM REQ UIREM EN T DETA IL S

Categories Choose a primary, a secondary, and up Read more


to four subcategories.

Industries Choose up to two industries for your Read more


offer.

App version Specify the version number of your Read more


offer.

Terms and conditions Outline the terms and conditions that Read more
the customer must accept before they
can use your offer.

Offer listing
IT EM REQ UIREM EN T DETA IL S

Offer name Enter a descriptive name for the offer. Read more

Offer summary A single sentence summarizing the Read more


purpose or function of the offer.

Description text Make an elaborate and compelling Read more


description that outlines the benefits
and usage scenarios of your offer
(include supported editions, countries,
and languages).

Search keywords Add search keywords to help users Read more


find your offer when they search in the
marketplace.

Products your app work with Add specific products that your app Read more
works with.

Help link The link to your offer’s learning Read more


resources.

Privacy policy link The link to your offer’s privacy policy. Read more

Support link The link to your offer’s support page. Read more

Supporting documents Add supporting sales and marketing Read more


assets such as white papers, brochures,
checklists, or PowerPoint presentations.

Logos Upload a large size logo file with Read more


dimensions between 216 pixels x 216
pixels and 350 pixels x 350 pixels.

Screenshots Provide a minimum of three Read more


screenshots that showcase your offer.
IT EM REQ UIREM EN T DETA IL S

Videos (optional) Add up to four videos that Read more


demonstrate your offer. These should
be hosted on an external video service.

Availability
IT EM REQ UIREM EN T DETA IL S

Markets (countries) Choose the markets that your app is Read more
available in (make sure that it
resembles the supported countries
paragraph in the description text).

Hide key The hide key is a token that is used to Read more
view the preview of your offer in
AppSource before going live.

How does my offer look when it's live on AppSource?


Marketing Validation FAQ
2/6/2023 • 2 minutes to read • Edit Online

Where do I state the countries, editions and languages that my offer


supports?
You're required to state the countries, editions and languages that your offer supports in the bottom of your
offer’s description text. You can use the following format:
Suppor ted Editions:
The app supports the Essentials and Premium Editions of Microsoft Dynamics 365 Business Central.
Suppor ted Countries:
Canada, Mexico and United States
Suppor ted Languages: This app is available in English (United States) and Spanish (Mexico).

Do you have any tips and tricks for what I should write in the
description text?
Yes. We have detailed guidelines and good advice about that here.

How do I refer correctly to the product?


When you mention the product, both throughout your description text, and in your marketing material, you
need to refer to the product, in the following way:
First mentions: Microsoft Dynamics 365 Business Central
Secondar y mentions: Dynamics 365 Business Central
Subsequent mentions: Business Central
Therefore, you can't use any abbreviations such as “MS Dyn 365 BC” or “Microsoft Dynamics NAV”.

What are the requirements for my offer’s help and support page?
You're required to submit two distinct pages for support and help that is, they cannot be the same. You can see
what you have to include on both pages in the table below.

H EL P SUP P O RT

Learning material such as FAQs, step by step guides, video At least two contact options (for example, e-mail, phone,
tutorials, webinars etc. chat) and a defined SLA for how much time it takes before
you answer to support inquires.

Can I use the Microsoft Dynamics 365 Business Central logo?


No, you can't use the Business Central logo, as it’s a Microsoft trademarked logo. However, you can use the “Get
it from Microsoft AppSource” badge, which you can find here.

See Also
Marketing Validation Checklist
Technical Validation
2/6/2023 • 8 minutes to read • Edit Online

Below you'll find a checklist of all requirements that you must meet before submitting an extension for
validation. You'll also find a description of how the Business Central Validation team is performing technical and
manual validation and how you can implement a validation pipeline to perform the same technical validation
yourself.

TIP
If you have questions around validation for your app, see Technical Validation FAQ for more information about who to
contact.

Technical Validation Checklist


If you don't meet these mandatory requirements, your extension will fail validation. To get code validation
helping you bring your extension package to AppSource, you can enable the AppSourceCop code analyzer. For
more information, see Using the Code Analysis Tool.

REQ UIREM EN T EXA M P L E/ GUIDA N C E

Develop your extension in Visual Studio Code. Developing AL Language extensions

The app.json file has mandatory properties that you must Mandatory app.json properties
include. The 'name', 'publisher', and 'version' properties must
match the values set in your offer description. Here you can
also read more about dependency syntax and multiple
countries per a single app syntax.

Coding of Date must follow a specific format (no longer Use the format yyyymmddD . For example, 20170825D .
region-specific)

Remote services (including all Web services calls) can use Guidance on HTTP use
either HTTP or HTTPS. However, HTTP calls are only possible
by using the HttpRequest AL type.

Only JavaScript based Web client add-ins are supported. The Control Add-Ins
zipping process is handled automatically by the compiler.
Include the new AL controladdin type, JavaScript sources,
and build the app.

The .app file must be digitally signed. Sign an APP Package File

Set the application areas that apply to your controls. Failure Application Area guidance
to do so will result in the control not appearing in Dynamics
365 Business Central.

Permission set(s) must be created by your extension and Exporting Permission Sets
when marked, should give the user all setup and usage Managing Users and Permissions
abilities. A user must not be required to have SUPER
permissions for setup and usage of your extension.
REQ UIREM EN T EXA M P L E/ GUIDA N C E

Before submitting for validation, ensure that you can How to publish your app
publish/sync/install/uninstall/reinstall your extension. This
must be done in a Dynamics 365 Business Central
environment .

Thoroughly test your extension in a Dynamics 365 Business Testing Your Extension
Central environment.

Don't use OnBeforeCompanyOpen or OnAfterCompanyOpen Replacement Options

Include the proper upgrade code allowing your app to Upgrading Extensions
successfully upgrade from version to version.

Pages and code units that are designed to be exposed as Web Services Usage
Web services must not generate any UI that would cause an
exception in the calling code.

You're required to register affixes for your publisher name Prefix/Suffix Guidelines
and to use them in your extension.

You're required to register an ID range for your publisher Object Ranges


name and to use it in your extension.

We strongly recommend you're using automated testing, Testing the Advanced Sample Extension
using the AL Test Toolkit. You aren't required to include the
test package with your extension.

DataClassification is required for fields of all tables/table Classifying Data


extensions. Property must be set to other than
ToBeClassified .

You must use the Profile object to add profiles instead of Profile Object
inserting them into the Profiles table.

Use addfirst and addlast for placing your actions on Placing Actions and Controls
Business Central pages. This eliminates breaking your app
due to Business Central core changes.

The extension submitted must not be a runtime package. Creating Runtime Packages

The extension submitted must use translation files. Working with Translation Files

The extension submitted must specify the Application The Application manifest property is required in order to
manifest property. compute the minimum release of Business Central targeted
by your submission. For more information, see Computation
of Releases for Validation

Technical validation performed by the Business Central validation


team
The primary responsibility of the technical validation is to ensure that the Business Central online service is
stable and that the apps can be installed and run without destabilizing the service.
The technical validation is fully automated and validates the requirements defined in the technical validation
checklist above.

IMPORTANT
It is recommended that all partners run the self-validation documented below before submitting apps for validation to
maximize chances of validation success.

1. The manifest of all extensions in the submission is validated. If any mandator y proper ties or required
proper ty values are missing, the submission is rejected..
2. The registration of affixes for the publisher name of all the extensions in the submission is validated. If the
publisher name does not have any registered affixes, the submission is rejected.
3. The signature of all extensions in the submission are validated. If any extension is not signed or its
signature is not valid, the submission is rejected.
4. The consistency of the main extension information (name, publisher, version) is validated against the offer
description. If any differences are noticed, the submission is rejected.
5. The extensions in the submission are validated. If any runtime packages are present, the submission is
rejected.
Once the extension has passed these first validation steps, the minimum release for your submission is
computed as described in Computation of Releases for Validation.
For each countr y and each release targeted by your submission, the following steps are run for each
extension in the submission:
1. If the extension with the same version has already been validated for the country, further validation for this
extension is skipped.
2. The set of dependencies for your extension is resolved. Any unresolved dependencies will cause the
submission to be rejected. If you include extensions created by Microsoft in your submission, it
will also be rejected.

NOTE
You are required to include the dependencies for your extension as part of your submission only if you are submitting a
newer version for them. If you do not include them in your submission, they will be downloaded automatically if they are
available in Business Central for the targeted countries/regions. If you are making your libraries available in new countries,
you should increase the version number.

3. The set of baselines for your extension is resolved by using the App Management API.
4. The extension is compiled against the set of dependencies resolved. If the compilation fails, the
submission is rejected.
5. The extension is tested against the resolved baselines using the AppSourceCop analyzer. If any violations or
breaking changes are identified, the submission is rejected.
6. If the runtime version of the extension is not suppor ted by the release targeted, the submission
is rejected.
If all extensions in the submission succeed the validation for each country and release without errors, the
submission is accepted..

Running technical validation yourself


With the latest version of BcContainerHelper, you can run a single command, which should perform the same
validation steps and give you a good indication of whether your apps will pass validation or not:
$validationResults = Run-AlValidation `
-validateCurrent `
-installApps @( "path/url to your foreign dependencies, apps which will not be part of the validation
(or blank if this is the first)" ) `
-previousApps @( "path/url to your previous version of the .app files (or blank if this is the first)" )
`
-apps @( "path/url to the new version of the .app files" ) `
-countries @( "countries you want to validate against (f.ex. us,ca)" ) `
-affixes @( "affixes you own (f.ex. fab,con)" ) `
-supportedCountries @( "supported countries (f.eks. us,ca)" )
$validationResults | Write-Host -ForegroundColor Red

All array parameters can also be specified as a comma-separated string. For more information, you can also
check this blog post Run-AlValidation and Run-AlCops.
Please include app and all library apps in both previousApps and apps and please include all countries on which
you want to validate.

NOTE
The Run-AlValidation cannot see whether the affixes to specify have been correctly registered with Microsoft using your
MPN ID and app publisher name, please make sure registration is in place.

IMPORTANT
The computer on which you run this command must have Docker and the latest BcContainerHelper PowerShell module
installed and be able to run Business Central on Docker.
If you are having issues with Business Central on Docker, you might be able to find help here:
https://freddysblog.com/2020/10/12/troubleshooting-business-central-on-docker.
You can use https://aka.ms/getbc?artifacturl=bcartifacts%2fsandbox%2f%2fus%2flatest to create an Azure VM, which has
all prerequisites installed to run Business Central on Docker.

NOTE
It is recommended that all partners set up DevOps processes to ensure that this validation process happens automatically
and regularly.
You can find resources for how to set up full plug-and-play DevOps processes using AL-Go for Github: https://aka.ms/AL-
Go.

How to get more information on the technical validation failures?


Detailed validation results are automatically logged to the ApplicationInsights storage account specified by
instrumentation key in the manifest of the main extension in your submission.
In order to enable partner telemetry in your extension, you must specify the
applicationInsightsConnectionString property in the manifest (app.json) of your extension. For more
information about this property, see JSON files.
In order to get started on analyzing your validation results, you can use this troubleshooting guide Dynamics
365 Business Central Troubleshooting Guide (TSG) - AppSource Submission Results (SaaS).
For more information about the signals sent during the technical validation, see Analyzing AppSource
Submission Validation Trace Telemetry.
Against which releases of Business Central is your submission
validated?
Extensions submitted to the AppSource marketplace are validated for all countries specified in the submission
against all the release targeted by the submission. As part of the validation, the minimum release for your
submission is computed. The extensions are then validated for all releases from this minimum release to the
current release in production. For example, if the minimum release for your submission is 18.0 and the latest
minor release in production is 18.3, your submission will be validated against 18.0, 18.1, 18.2, and 18.3.
The minimum release for your submission is computed based on the application property specified in the
app.json of your extension.

NOTE
If multiple extensions are contained in your submission, the minimum release for the submission is the highest minimal
release computed for each of the extensions in the submission.

IMPORTANT
The minimum release computed for your submission also defines the availability in Business Central of all the extensions
in your submission.
For example, if the minimum release computed is 18.1, your extensions will be available starting from release 18.1.

Example
If your extension's manifest is defined as follows, the minimum release where your extension can be installed is
18.0 because the manifest requires the Application extension to be available with a version higher or equal to
18.0.0.0.

{
"application": "18.0.0.0",
}

The minimum release of the extension is then 18.0.


For AppSource extensions, it's now required to use the application property instead of explicit dependencies
on the Base Application and System Application . For more information, see The Microsoft_Application.app File
and AS0085.

See Also
Developing AL Language extensions
Technical Validation FAQ
2/6/2023 • 21 minutes to read • Edit Online

This article addresses some of the most frequently asked questions around validation of apps for AppSource
submission.

Questions about the validation process


In the following, you can read about how submissions are handled and learn how to address the most common
scenarios.
Against which releases are my apps validated?
The extensions in your submission are validated for all the releases targeted by your submission.
Based on the app.json file of your extension, the service automatically computes the minimum release targeted
by your submission and the extensions are then validated for all releases from this minimum release to the
current release in production. For more information, see the example in Technical Validation Checklist. The
'Target Release' (Current, Next Minor, Next Major) available under 'Supplemental Content' in Partner Center is
ignored and will be removed.

IMPORTANT
The minimum release computed for your submission also defines the availability in Business Central of all the extensions
in your submission.
For example, if the minimum release computed is 18.1, your extensions will be available starting from release 18.1.

NOTE
30 days before the release of a new Business Central major version, all submissions are validated against the upcoming
release. The apps in your submission must then be compatible with the upcoming release. The goal is to ensure that your
customers won't be blocked during the upgrade of their environment.

Against which countries/regions are my apps validated?


The extensions in your submission are validated for all the countries/regions targeted by the submission, which
are available in Business Central. You can see which countries/regions you've selected in Partner Center under
Availability > Edit Markets .

When you're adding new localizations in Business Central, these countries/regions can be added to Partner
Center before they're ready in Business Central. If you're targeting a country/region marked as 'Planned' in
Country/regional availability, depending on when your submission is processed, your apps might not be
uploaded to Business Central if the localization isn't yet ready in Business Central. Generally, it's possible to
upload apps for 'Planned' localizations a few weeks before they're officially released. When the localization
becomes available, if you're experiencing issues installing your apps, you should increase the version in the
app.json and submit the packages again in Partner Center. If you're using Azure Application Insights, you can
check whether the country/region was validated using this Troubleshooting Guide (TSG).
Against which baselines are my apps validated?
The service will verify that your extensions don't introduce breaking changes by comparing them to the latest
version available in AppSource for each country validated.
You can know which versions of your extensions were used as baseline during the breaking change validation
by enabling Azure Application Insights in your extension and running this Troubleshooting Guide (TSG).

IMPORTANT
As soon as your app has been uploaded to the AppSource marketplace, it will be used as a baseline during the technical
validation of your next submissions. As a consequence, you won't be allowed to perform breaking changes without
obsoleting the AL objects first and you won't be allowed to perform schema breaking changes; breaking changes on
tables or table extensions. This applies also if your extension isn't used by customers yet. You should then not submit your
app to the AppSource marketplace if you are still developing it and expect to change it in the near future.

Which apps are validated in my submission?


The main app and the libraries required by the main app are validated and uploaded to Business Central. If you
have included libraries, which aren't required by the main app, they'll be ignored during the validation and won't
be uploaded to the service.
For example, let's consider an app A, which has an offer in the AppSource marketplace and A depends on a
library named B, which doesn't have any dependencies. If you create a new submission with A as the main app
and include B, C, and D as libraries, then only A and B will be validated. C and D will be ignored because they
aren't required by the main app A. If B is updated to depend on C and D, then all apps in the submission will now
be validated by the service.

NOTE
If some apps in your submission already have been uploaded to Business Central with the same version for some
countries/regions, then the app will not be validated again for these countries/regions.

IMPORTANT
If one or more libraries in your submission have their own offer, their listing(s) in the AppSource marketplace won't be
updated automatically. In order to keep the listing(s) in sync with the version of the app(s) uploaded to Business Central,
you should submit a submission for their related offer(s).

How long does the 'Automated application validation' take?


During 'Automated application validation', the apps in your submission are validated for each of the
country/regions and each of the releases of Business Central targeted. If you already have a version of these
extensions published to AppSource, then it will also run the breaking change validation using the apps currently
in AppSource as baseline. Depending on the size of your app, the validation time can vary. Submissions are
processed within a few minutes and we expect all submissions to be processed under 3 hours. However, if your
app contains thousands of AL files, this process can take longer. We would then recommend splitting the app in
smaller modules as it would also improve the development experience and the maintainability of your code
base.
How many automated tests do we need to run for validation and how high must the test coverage be?
When setting up your offer in Partner Center, you must still include a test package in 'App Tests Automation', but
it isn't used during the validation of the submission.
Test automation is something we expect you to run, to test your app and to make sure that the quality of your
app is high. We don't run tests of your apps, nor do we have a set value for a required code coverage. Instead,
we rely on you to test your app properly to give your customers a good experience.
When I submit an app to AppSource; do you always make a manual validation based on the provided 'Key
Usage Scenario' document?
When setting up your offer in Partner Center, you must still include a document in 'Key Usage Scenario', but it
isn't used during the validation of the submission.
We don't run a manual validation of the apps anymore. Instead, we rely on you to test that your app provides
your customers with a good experience.
When are my apps ready to be installed in my Business Central environment?
Shortly after the offer publishing process has been completed in Partner Center, your extensions will be
available for installation in Business Central.
Business Central currently doesn't support installing offers at the "Preview creation" step.
When should I include my library apps as part of my submission?
You aren't required to always include the dependencies of your extension as part of your submission.
You're only required to include the dependencies for your extension as part of your submission if you're
submitting a newer version for them. If you don't include them in your submission, they'll be downloaded
automatically if they're available in Business Central for the targeted countries/regions.

NOTE
If you include the dependencies of your extension as part of the submission, these dependency versions will be used
during the validation, even if there are higher versions already available in Business Central.

If you didn't include the dependencies for your app and they aren't available, your submission will fail during the
"Automated Application Validation" stage. Failing to find the dependencies for an extension results in error
messages with the diagnostic codes AVS0005 or AVS0101 .
If you receive an error with the diagnostic code AVS0107 and a message similar to
The extension 'MyApp' by 'MyPublisher' (version '1.2.3.4') has already been uploaded to Business Central for
the country/region 'US'
for one of your library apps, it means that you've already published another .app file for this extension to
Business Central as part of a previous submission. This can happen if you submit a .app file with different
content, or created by a different build (each .app file created has a specific build ID stamped, so building
multiple times the same project results in .app files with different build IDs). If this version of the library is
already available for all countries targeted by your submission, you can just remove the extension from the
submission. If you're making your library available in new countries, you should use the .app file that has
already been uploaded to Business Central or increase the version number in the manifest of the extension (the
app.json file).
My app failed at the "Automated application validation" stage, what do I do next?
At this stage, your extensions are validated to assess whether they meet the requirements specified in the
Technical Validation Checklist.
If this stage failed with an error message similar to
The validation of the submission failed for X out of Y tasks , you must investigate what has caused the error.
If you're using Azure Application Insights, information about the validation results is logged in Azure Application
Insights. You can also use this Troubleshooting Guide (TSG) in order to get started. If you're experiencing issues
with Azure Application Insights, refer to the dedicated section below.
If this stage failed with an error message similar to
The extension 'MyApp' by 'MyPublisher' (version '1.2.3.4') has already been uploaded to Business Central for
the country/region 'US'
, you must update the list of extensions submitted. For more information, see "When should I include my library
apps as part of my submission?".
If this stage failed with an error message similar to
The submission must target at least one existing country/region of Business Central , your submission doesn't
target any countries/regions currently available in Business Central. If your submission targets a country/region
marked as 'Planned' in Country/regional availability, you must wait for the localization to become available in
Business Central and resubmit your offer. Generally, it's possible to upload apps for new localizations, a few
weeks before they're made available to customers.
If this stage failed with an error message similar to
The extension 'MyApp' by 'MyPublisher' (version '1.2.3.4') contains inconsistent information about the
package id/name/publisher/version
, it means that something went wrong when the package included in your submission was built. In order to
mitigate the issue, you must rebuild the package and submit it again.
If this stage failed with an error message similar to
The App ID '<some-Guid>' is already used for Per-Tenant-Extensions in Business Central and cannot be used for
the AppSource extension with name 'MyApp' and publisher 'MyPublisher'
, this means that there exists one or many PTEs with the same App ID in the service. Since Business Central
doesn't support having AppSource apps and PTEs with the same App ID, it's then recommended to change the
ID of your extension before submitting it in Partner Center. For more information, see Moving a PTE to
AppSource. If the PTEs with that App ID aren't used in any customer environments anymore, you can create a
support case in Partner Center to request an exception.
If this stage failed with the following error message
Automated validation of the submission has failed. Please retry the operation and contact Partner Center
support if it fails again.
, you should create a new submission in Partner Center. If your submission fails again, you should create a
support case in Partner Center as documented in this article.

NOTE
Because the extensions in your submission are validated for each release and country/region targeted by the submissions,
the validation results can be really verbose and cannot always be displayed in their full length in Partner Center. The error
message will then end with ...(Truncated) . If that happens for your submission, you should either enable Azure
Application Insights in your extension, run the self-validation script, or fix the errors visible and iterate on your submission.

My app failed at the "Certification" stage, what do I do next?


At this stage, your extensions are validated to assess whether they meet the requirements defined in the
Marketing Validation Checklist.
Review the Marketing requirements and the Marketing Validation FAQ in order to fix the errors reported.
My app failed at the "Publish application with the service" stage, what do I do next?
At this stage, your extensions are being published to Business Central.
If this stage failed with the following error message
Automated upload to Business Central of the extensions in the submission has failed. Please retry the
operation and contact Partner Center support if it fails again.
, you should create a new submission in Partner Center. If it fails again, you should create a support case in
Partner Center as documented in the dedicated section below.
My app failed at another stage, what do I do next?
If your submission failed at another stage than "Automated application validation", "Certification", or "Publish
application with the service", you should create a support case in Partner Center as documented in the dedicated
section below.

Questions about Azure Application Insights usage during AppSource


submissions
How do I enable Application Insights telemetry for my submissions?
To enable Application Insights signals for your submissions, you must specify the
applicationInsightsConnectionString property in the manifest (app.json) of your extension. For more
information about this property, see JSON files.
I don't see any signals in the resource specified for my extension, what do I do next?
Here's a list of steps that you can follow to troubleshoot this issue:
1. Validate that the Application Insights resource queried is the same one as specified in the manifest (app.json)
of your extension.
2. Validate that the time range when running the query covers the time of the submission.
3. If you're using the applicationInsightsKey property in the manifest (app.json) of your extension, you should
use the applicationInsightsConnectionString property instead because it's more reliable. Make sure to use
the full connection string from your Azure Application Resource.
4. If you're using the applicationInsightsConnectionString property in the manifest (app.json) of your
extension, make sure that you're using the full connection string and that it contains, at least, the following
key-value pairs: InstrumentationKey=<some-key> , IngestionEndpoint=<some-url> , and LiveEndpoint=<some-url>
. For more information, see Connection strings
5. Validate the data sampling and daily cap set for the Azure Application Insights resource. Navigate to the
resource in Azure and go to 'Configure > Usage and estimated costs'. Validate that your Application Insights
retains all data (data sampling is set to 100%) and that you haven't reached your daily cap. For more
information, see Sampling in Application Insights.
I can see some signals in Application Insights, but I can't find why my submission failed, what do I do next?
Much information is provided in the custom dimensions of the signals. The validation errors can generally be
found for the signals with eventId LC0034 . For more information about the signals emitted during the technical
validation of AppSource submission, see Analyzing AppSource Submission Validation Trace Telemetry.

NOTE
Instead of writing your own queries, we recommend using the executable Azure Data Studio Troubleshooting Guide (TSG).
This guide contains queries that will process the signals for your submission and extract the important information.

Questions about developing and maintaining AppSource apps


This section contains frequently asked questions regarding developing apps (in Docker or SaaS). Fore
information, about maintaining apps after they've reached the AppSource marketplace, see Update Lifecycle for
AppSource Apps FAQ.
What does it mean if I have an app in development that needs another dependency loaded, but I can't get
the dependency's codeunits to load in my BC docker instance because it says the dependency's range is
outside my range?
It means that your license doesn't allow you to publish that application. A recommendation would be to either
get a runtime package from the developer of that AppSource app, which will allow you to bypass the licensing
check or to try to test it on an online sandbox environment where that AppSource app is already installed.

Questions about code-signing validation


This section contains frequently asked questions related to the code-signing requirement from the Technical
Validation Checklist. For more information about code-signing, see Sign an APP Package File.
Can I use a self-signed certificate to sign my apps targeting AppSource?
No, it isn't allowed to use a self-signed certificate. The .app package file must be signed using a certificate
purchased from a Certification Authority that has its root certificates in Microsoft Windows. You can obtain a
certificate from a range of certificate providers, including but not limited to GoDaddy, DigiCert, and Symantec.
Do I need to use an EV code -signing certificate to pass the technical validation?
No, it isn't required to use an EV code-signing certificate. Standard code-signing certificates can be used to
satisfy the code-signing requirement.
Can I reuse the same code -signing certificate to sign multiple apps?
Yes, you can reuse the same code-signing certificate for multiple extensions. Code-signing certificates have a
validity period defined over time.

Questions about names, affixes, and ID ranges


In the following, you can read about how affixes and ID ranges are assigned.
Do I need to register different affixes for each of my extensions?
No, you don't need to register affixes for each of your extensions.
The object affixes are registered per publisher so if your apps all have the same publisher, they can share the
same affixes. The automated validation verifies that you're using the three letter affix registered by Microsoft in
your extension, but this still allows you to create longer affixes per extension. For example, if you registered ABC
as your affix, you can use ABCD as the prefix in Extension 1 and ABCE as the prefix in Extension 2. For more
information, see Prefix and suffix for naming in extensions.
Do I need to request a different ID range for each of my extensions?
No, you don't need to request a new ID range for each of your extensions.
The object IDs are registered per partner, not per extension. You can then use a subset of this range for each of
your extensions. It is your responsibility to ensure that you aren't defining objects with the same IDs in different
extensions. If you're doing so, the extensions defining these objects can't be installed together on the same
environment. For more information, see Get Started Building Apps.
Will there be any changes made to the object names character limitation (30 characters) within the near
future?
We would like longer names as well. Introducing namespaces could be one investment. However, such a change
has down-stream breaking impact (any caller needs to qualify calls) and there are SQL constraints on name
lengths for tables, which currently include company name, table name, app ID and needs to be maximum 255.
This is on our long term backlog, but haven't any changes planned soon.

Questions about app identity


This section contains questions related to the identity of apps in AppSource. For more information, see the
questions in App Identity.
When is it okay to change the name of my extension?
Starting from Business Central 2021 release wave 2 (version 19.0), it's possible to change the name of your
extensions without breaking dependent extensions.
When renaming an extension, you must:
increment the version number in the manifest of your extension,
make sure that your submission only targets releases of Business Central starting from 19.0.
update the name of your offer in Partner Center - if your extension is the one for which the offer is created.
When is it okay to change the publisher of my extension?
Starting from Business Central 2021 release wave 2 (version 19.0), it's possible to change the publisher name of
your extensions without breaking dependent extensions.
When changing the publisher of an extension, you must:
increment the version number in the manifest of your extension,
make sure that your submission only targets releases of Business Central starting from 19.0,
contact d365val@microsoft.com in order to register your affixes to your new publisher name.
When is it okay to change the App ID of my extension?

IMPORTANT
The App ID is a critical part of the identity of apps in Business Central, and changing it is a breaking change for all
extensions depending on it. You should then not change the App ID of extensions which are installed for customers in
Business Central Online.

If you are submitting a new version of your extension with a different App ID for an existing offer, then this new
version will be considered as a different extension. This means that all extensions that depend on the extension
with the old app ID must be updated to reference the new App ID. If they are not updated, this will cause issues
such as customer environment upgrade failures which must be fixed within the required time period, see
Maintain AppSource Apps and Per-Tenant Extensions in Business Central Online. Since the app ID is part of how
data is stored in Business Central, this also means that you will have to migrate the data for all customers that
have the extension with the old App ID installed. Note that we do not provide tools for performing data
migration in SaaS, but you can create your own solution to export data from the old extension and re-import
the data after the extension change.
Is it possible to have multiple apps with the same App ID in AppSource?
Each unique codebase has one unique ID. If you have four apps in AppSource, you need to have four unique IDs
for these apps. Otherwise you'll get conflicts.
What if we already have an app on AppSource but we need to create the same app for another country; can
we then have the same app ID for two different apps targeting two different countries?
If they're different apps (different code), they should have different identity. Identity is used in, for example, app
management, dependencies, support cases, and telemetry. If reused across different apps, identity uniqueness is
lost. Another approach could be a common shared (internal/library) app across countries (with one app identity)
and localized functionality as extensions on top (with their own identity).

Questions about Business Central offers


When is it okay to change the offer type of my offer?
There exist two types of offers for Business Central in AppSource: connect apps and add-on apps. It's possible
to change an offer type from connect to add-on by following the steps listed in the dedicated entry below.
However, we don't recommend changing an offer from add-on to connect since it would be a breaking change
for all other extensions depending on the apps in this offer.
For more information about the offer types for Business Central, see App type, contact type, and customer leads.
How to change the offer type from 'connect' app to 'add-on' app?
When changing a connect app to an add-on app, you should:
Navigate to your offer listing in the AppSource marketplace, and copy the URL for your offer
Retrieve the App ID assigned by the service to your offer: the App ID can be found as <appId> in
https://appsource.microsoft.com/en-us/product/dynamics-365-business-central/PUBID.<publisherId>%7CAID.
<offerId>%7CPAPPID.<appId>
Use this App ID in the app.json of the main extension uploaded to your offer

NOTE
The App ID is used as part of the URL of the offer listing and is used as a key to retrieve to customer review left on the
offer listing. Not preserving the App ID means that the offer URL will change and customer reviews will be lost.

How to automatically update my offer using Partner Center submission API?


It is possible to automatically submit apps to AppSource from our DevOps setup by using the Partner Center
Ingestion API. For more information, you can also check this blog post Automatic AppSource Submission of
Business Central apps.

Channels to ask questions or report issues


In the following, you can read about how you reach out for support most efficiently.
When do I contact d365val@microsoft.com?
When registering affixes for your publisher, or adding a new publisher name to your affixes. When contacting
d365val@microsoft.com, make sure to provide the required information documented in Benefits and Guidelines
for using a Prefix or Suffix.
When do I contact Partner Center customer support?
When your submission fails to be successfully completed in Partner Center, but you're experiencing issues
updating your extension(s) to fix the validation errors.

IMPORTANT
If you're using Azure Application Insights, before opening a support case for a failure at the 'Automated application
validation', you must analyze the signals emitted in your Azure Application Insights storage. You can do so by using the
Troubleshooting Guide (TSG). When opening a support case, you must include the Kusto queries you used and the
diagnostic messages that you found. Including the results from the TSG is also recommended.

When do I contact Business Central customer support?


When your submission has been successfully completed in Partner Center, but your customers are experiencing
issues installing or using the app.
When do I log an issue on NavContainerHelper on GitHub?
When you have questions or bugs regarding the self-validation script, or any of the modules exposed by
BcContainerHelper.
For more information, see https://github.com/microsoft/navcontainerhelper/issues.
When do I write on Yammer?
When you have questions on developing and maintaining AppSource apps, on automatically submitting apps to
AppSource, or about the validation process, you can ask a question on Yammer. In this group, you'll find
announcements from Microsoft together with discussions around various AppSource-related articles.
You can join this AppSource group at aka.ms/BCYammer (note that you need to be a Microsoft partner to do so).
If you have problems connecting, email dyn365bep@microsoft.com.

See also
Technical Validation Checklist
How to Make Compelling Videos
2/6/2023 • 9 minutes to read • Edit Online

Why use video? It's worth investing time and resources to create marketing videos for your app, it's taken
seriously in a business environment.

Reasons why video is a superior medium


Videos offer a rich, stimulating communication medium that engages multiple senses.
Video engages the mind and triggers emotions, which makes it more compelling than text-based content.
Our brains have an easier time processing visual stories than bullet points or straight facts.
A recent Demand Gen survey indicated that 58% of B2B buyers consume video content, while Hyperfine media
states that 59% of executives would rather watch video than read text. Also, 50% of executives look for more
information after seeing a product/service in a video.

Speak to Specific Personas in your videos


You should create a video for each of the three core personas in the company:
WHY persona: Owner/executive/leadership
HOW: Business line manager
WHAT: IT buyer, User
A horizontal generic message that attempts to speak to everyone will likely not reach anyone in an emotionally
engaging way. Wasting a prospect’s time by requiring the prospect to listen to irrelevant data or information will
only create frustration and lead the prospect to form a negative bias towards your company.

Choose the video format that is relevant for the audience that you
want to target
Video type 1: “Why” video
How to set up “Why” videos
Recommended length: 60-90 seconds
Purpose:
Your video should clearly communicate WHY prospects need to buy your solution now.
Focus:
Make sure the prospect is the hero of the story, not you or your company. Prospects aren't interested
in hearing about your company at this stage. They're simply trying to determine if what you offer is of
value to THEM.
Your video should speak to the principal challenges and goals of your core decision-maker persona.
Describe the desired end state they'll achieve by using your app.
A client/customer speaking about the benefits they received from your app is far more credible and
compelling than anyone from your organization.
Don’t only rely on “features” to acquire new customers.
How to speak to a WHY persona in a video
Target audience:
Owner/executive/leadership
They have limited time and financial resources as well as many competing priorities and resource
requirements
You need to elevate the discussion to a strategic level, where you highlight market share,
competitiveness, profitability, differentiation, revenue loss, and more.
Message:
The question you must answer beyond a doubt is WHY should they invest the time and money to buy
your app? What will they get out of it?
Why should they spend money on a new system now? Can’t they put it off?
The WHY messaging teaches people something and it's industry specific and results oriented, as well
as being memorable. It engages the emotional/limbic brain and leads to meaningful action.

Video type 2: “How & What” video


How to set up “How and What product videos”
Recommended length: Up to 3 minutes.
Purpose:
This video goes into greater depth communicating the main benefits of your app and HOW you solve
your prospects’ problems. You can include some WHAT content. • Focus:
Demonstrating the proof of your claims is critical during this video.
Show specific dashboards or visually show how you address prospect challenges.
If possible, use contrast to create desire and a sense of urgency. For example, you could show a
complex, ugly data-filled forecast spreadsheet next to a beautiful visual dashboard stating “your sales
forecast before and after.”
How to speak to a HOW persona: (Business line manager)
Target audience: Business Line Manager
HOW focuses on the operational benefits your solution will provide and HOW your organization will
support the implementation.
Speaking to the HOW persona starts to separate you from the pack. • Message: o HOW content is
VISUAL in nature and ACTION oriented. It allows your prospects to identify with you at a
FUNCTIONAL business level and to add on with you. It provides evidence that your organization has
relevant industry experience. Tribal acceptance increases, while risk decreases.
HOW messaging begins to appeal to the limbic brain because it's focused primarily on emotional
business pains and problems.
How to speak to a WHAT persona: (IT buyer, User)
Target audience: IT-buyer, User
WHAT people are often tasked with finding a solution and are important influencers in the decision,
but they aren't the financial decision makers, and their opinions are easily overturned by HOW and
WHY people in the organization.
Therefore, don’t invest all of your marketing time, money, and effort into providing content just for
them.
Message:
You need to survive the WHAT inquisition and provide information about product-related features,
functionality, and data so that prospects clearly understand your solution offering.
However, this will seldom trigger an emotional response and, therefore, it's likely there will be little or
no emotional engagement with your content.
WHAT content is binary. WHAT content is a commodity. WHAT content is boring. Logical WHAT
content is a necessary evil because many prospects initially go looking for it, but stopping here means
remaining relevant only to WHAT personas.

Video type 3: “Getting started” video


How to set up “Getting star ted videos”
Recommended length: 2–3 minutes maximum.
Purpose: This video should prove it's quick and easy to get up and running with your app.
Target: What personas (Users, It buyers)

Video type 4: “Customer testimony” video


How to set up “Customer testimonial videos” - Recommended length: Up to 2 minutes
Purpose:
Social reinforcement: Customer stories are the best proof of gain.
Focus:
A story coming directly from your client in the form of a testimonial is stronger than having your
prospects take your word for it. If prospects see that other similar people or companies have already
purchased your solution, then their natural response will be to more readily accept it as a solution for
themselves.

Video tips
How to structure your video and practical things to keep in mind when producing videos
How to structure the flow in your video?
Gain immediate attention in the first 10 seconds of the video Stimulate curiosity by including a hook
phrase/comment that will elude to solving a pain point. Ask questions about the prospects’ core business
challenges or ask about something they would like to do but can’t accomplish today.
Highlight the prospects’ problems: Use an empathetic approach when describing their current situation and
demonstrate that you understand their current business challenges. They must relate to this if they're to
continue watching.
Give them new learning Teach them something they don’t know. Demonstrate you have expertise and
knowledge about their business or industry that they might not. Show you can offer strategic value to them.
Paint a picture of a desired outcome they would love to have or state they crave to experience. Highlight the
benefits, rewards, and value they'll enjoy after they purchase from you. Include both what it looks like and
how it will feel.
Prove what you’re saying is true Prospects don’t trust us when we say our products are great. Include
objective and credible proof in the form of data, charts, graphs, quotes, statistics, or testimonials as evidence
of your claims.
Ask them to take action. Include a call to action at the end of all videos. When viewers watch your videos,
they should feel inspired to take the next step towards purchasing. Tell them what to do next and include an
interactive link to the next step in the buying cycle. Use scarcity to compel them to action. Provide a time
limited offer or, for example, say it is “only for the first 20 customers”.
Practical things to keep in mind when producing and distributing your video
Does and don’t when producing your video
Don’t make the video too long As our attention span is 8 seconds the ideal length of video is 90 seconds
(minimum 30 seconds/maximum 2 minutes).
Add interactivity where possible Overlay text, charts, animation, questions etc. Visually call out key messages.
Make sure your audio is high quality.
Make your video easily shareable
Enable your video to be shared on multiple media. Track views and attention span. Observe and measure
viewer patterns so that you can learn from prospects’ actual behaviors and then improve future content.
How to make a good narrative that speak to the right persona in the right way?
Your narrative should have a beginning, middle, and end.
Lead with a story, not with your app or the technology.
Don’t turn your videos into a product pitch.
You’ll build more brand affinity and trust by shedding light on a problem your prospects care about
rather than by pitching your solutions to them directly.
The brain is on alert at the beginning of the video and at the end.
Make sure the first and last 10 seconds are compelling, memorable, and interesting.
Speak directly to a particular persona in the second person.
Don't talk about them in the third person, and avoid using terms like “our clients” and “companies”;
instead, use “you” language as often as possible.
Use many industry specific vocabulary, terminology, and visuals. If possible, film onsite at a
customer’s location rather than in your office or in a studio.
Speak to a particular persona:
Don't try to appeal to everyone at once, as you may not fully engage anyone with this approach.
Keep your delivery casual and authentic to instill trust. Speak directly to the prospect as if you were
having a fireside chat
The prospect should be the hero of the story, that is, don't speak about you and your company.
Ask rhetorical questions that stimulate pain and anxiety in your prospects in order to demonstrate that you
understand their business problems.
For example: Are your margins decreasing? Having cash flow problems because you can’t collect
payments sooner than 90 days? Had another large write-off? Lost an important customer recently
due to a late delivery?
Use visual and auditory language to help the prospect imagine a new possible future.
For example: “imagine seeing”, “picture yourself”, or “how would you like to hear your clients say…”
and so on.
Use contrast whenever possible.
Compare prospects’ experience now versus what it could be after the implementation of your
solution.
Call out your competitive differentiators while anchoring your solution in prospects’ minds so that
they can compare all others against the bar you set.
How to make a good narrative that speak to the right persona in the right way?
Where possible, use tangible, concrete language.
Include quantifiable proof in the form of data or visual pictures.
No vague claims like “transform your business with the cloud”. This is an emotionless statement.
Providing customer references and testimonials is much more compelling and effective than selling your
company or product yourself.
Let others speak for you. A customer testimonial video will always be more believable and compelling
than a video of you saying the same thing.
Surprise and delight them.
Use humor to make them smile. We take ourselves and our problems too seriously. Be warm,
memorable, and unique.
Guideline on Creating an Effective Sales Landing
Page for Your App
2/6/2023 • 10 minutes to read • Edit Online

Building a landing page that drives a successful buying transaction


Microsoft will drive qualified traffic to AppSource. Though, once a prospect becomes aware of your app, it will
be your job to guide them through to a successful buying transaction. Deliberately mapping and architecting the
buying journey is critical to ensure a high level of engagement and conversion. Only presenting your app’s
features and functionality, or just providing a free trial, won't ensure prospects will become buyers. For this you
need to have a good landing page that is built to help you capture attention, accelerate your customer
acquisition process, and drive buying behavior. The recommendations on this page will help you do so.

Examples of how other partners have implemented our best practices


To inspire you in creating a good landing page for your app, two of our valued partners, LS Retail and Industry
Built, have offered to provide a sample of what a best practice landing page for a Microsoft Dynamics 365
Business Central partner could look like.
Have a look at their app landing pages and use them as inspiration to build your own landing page:
Industry Built’s Build Food app
LS Retail’s LS Express Start app
In the following checklist, we have “broken down” the elements, on their landing pages in order to showcase
best practices on design and messaging. More specifically, we're looking into layout and structure elements,
content elements, visual elements, anxiety reducing elements and support elements.
Additionally, we have provided specific recommendations on how to apply these elements to help you increase
conversion and maximize the effectiveness of your product’s sales landing page.
We urge you to review and implement these best practices on your landing page – in so doing you'll contribute
in providing the Microsoft community of customers with a consistent buying experience across publishers.

Layout and structure elements


EL EM EN T DESC RIP T IO N EXA M P L E

Company Include the company logo on the page

App name & app logo Include a visual logo of your product
name and a one sentence positioning
statement.

Top menu choices Use clean, straightforward and


descriptive menu options.
EL EM EN T DESC RIP T IO N EXA M P L E

Search box Include a search box so visitors can


quickly find what they're looking for.

Emotional tribal anchor photos Visuals create an emotional Add-


onion. The brain skims over non-
emotional photos.

Visual Make your page easy to scan, with lots


of strong visual imagery.

Logo
The upper-left corner of the landing page is the most valuable section of the entire landing page.
Place your company logo in this location.
If you need help with formulating a positioning statement, try the value proposition generator located at here.
There should ideally be 5 or fewer choices; don't include more than seven options.
The menu text should state what the prospect gains if they select on the menu item
The text should be written from their perspective, not yours.
Recommended menu items:
How to Buy, Benefits Gained, Why Us, and Contact.

The upper-right corner of the page is usually an ideal spot


Faces evoke more emotion than landscapes or machines, and so on.
Include a happy customer that looks similar to your prospect in terms of age, demographic, and industry, and
which shows them dealing with the issues that your prospect can relate to.
Try not to use stock photos of people or objects.
Engagement
Too much text forces the brain to skim, skip, and exit. Text engages the logical, analytical brain, but not the
emotional brain.
Keep it clean and straightforward in terms of design and layout. Use lots of pictures, graphs, and screenshots
to enhance engagement.

Content elements: Text and messaging


EL EM EN T DESC RIP T IO N EXA M P L E

Include a headline question Get your prospects’ attention by “Struggling to manage your ingredient
asking them a compelling pain-based inventory and fretting over allergens?”
question that they can relate to.

You want the prospect to mentally say


“YES” as often as possible and to peak
their curiosity enough to read more.

Your questions should be intriguing


and customer-centric.
EL EM EN T DESC RIP T IO N EXA M P L E

In general, 8 out of 10 people will read


headline copy, but only 2 out of 10 will
read the rest.

Microsoft Dynamics 365 product Somewhere on the landing page, make Insert this paragraph: Microsoft
description sure you include the standard Dynamics 365 Business Central is a
Microsoft Dynamics 365 Business comprehensive business management
Central product description provided solution for small and medium-size
by Microsoft This is a requirement businesses (SMBs) that have outgrown
because your product is adding value their basic accounting software. From
to and building on this foundational day one, this new application makes
solution. ordering, selling, invoicing, and
reporting easier and faster. Dynamics
365 Business Central is deeply
integrated with Microsoft 365 and
includes built-in intelligence, so it's
easy to use and helps users make
better business decisions.

Messaging (Address their pains) Pain is a strong motivator of action.

- - Identify 1-3 key sources of the


client’s most prominent pain early on
the page.

- - Call out the fears that are likely to be


holding them back.

- - Your landing page text and


messaging should predominantly focus
on the pain the prospect is
experiencing, and NOT the features of
your product or service.

Clearly demonstrate to your prospects - Describe the business challenges


that you genuinely understand their they're facing now and the ways their
industry and unique business revenue growth, margins, productivity
problems. and so on, are being negatively
impacted by not taking action now.

EL EM EN T DESC RIP T IO N EXA M P L E

Messaging (Product benefits) Paint a clear, visual and desirable


picture of what is possible.

- Describe the most significant benefits - For example, “Save time and money
and rewards that your prospect will (benefits) by having a system that
realize after purchase. does all the tracking and calculations
for you (features).”

- - Don’t only list features and app


functionality, start with the benefit
first, then you can follow with the
features.
EL EM EN T DESC RIP T IO N EXA M P L E

- - Paint a picture of a possible


experience the prospect will
immediately desire.

- Clearly articulate a compelling desired - If possible, use industry-specific


outcome language and vocabulary to resonate
with your prospect deeply.

- - Choose a particular persona to speak


to directly.

- - Engage prospects by speaking


directly to them using first person
“you” language.

EL EM EN T DESC RIP T IO N EXA M P L E

Messaging (Prove your claims) Include specific calls-to-action on your “Reduce how long it takes to set up
app page. your recipes in the morning from 1
hour to 10 minutes.”

- Don’t make general and abstract -


claims.

- Use data as often as possible to


support your statements.

- If you make specific claims, support


your claims with proof, while
Quantifying impacts and gains.

- The more specific and concrete your


promise of value is, the better.

- Abstract concepts such as “more


efficiency, more productivity, transform
your business” aren't emotionally
impactful or convincing and don't
compel a prospect to act.

Target market - If you support multiple countries or languages, this is a key selling feature. • Find a way to show
this visually.

EL EM EN T DESC RIP T IO N EXA M P L E

Messaging (Compelling call-to- Include specific calls-to-action on your


action) app page

This can be your free trial; a time-limited special price; a scheduled walk-through demonstration; and so on.
The words "free” and “save” are highly emotional words in the English language, so they should be used.
Use bright colors, such as orange, yellow, or red, to call attention to your buttons.
Button text should use benefit language rather than descriptive language.
For example, instead of “Download” write “Click here to start saving money now.”
Try not to send prospects away from your page – always have an embedded next step in your call to action
that brings them back to your landing page.

EL EM EN T DESC RIP T IO N EXA M P L E

Messaging (Create a sense of Help your prospect gain a sense of Your bakery profitability will decrease
urgency by teaching the urgency to buy by teaching them one over the next five years due to an
prospects) thing about how they can be more increase of 3% in the cost of key
efficient or profitable now. inputs, such as wheat and sugar. Want
to know five key strategies that can
help you mitigate this challenge? Click
here to find out how to preserve your
profit margin

Show them how their performance in one key business area is below that of their competitors.
For an example you can provide a quick online self-assessment, a top-10 tips blog post, and much more.
Visual elements

EL EM EN T DESC RIP T IO N EXA M P L E

Pictures (Differentiation Show them, don’t tell them Show the before and after state.
comparison images)

This is a visual image of how your prospects do things now versus how they'll be able to do it in the future.
You aren't telling them but showing them using a visual.

EL EM EN T DESC RIP T IO N EXA M P L E

Compelling proof screenshots Visually demonstrate all the claims that Quickly and easily view inventory
you're making. items.

Graphic dashboards are the most effective method.


Zoom in on the main benefit-related features.
Make sure it's readable, and the benefit is obvious.
Include a caption.
Data should be industry specific so that it resonates with the viewer.
You want prospects to see how their data/process would look in your system.

EL EM EN T DESC RIP T IO N

Videos (Tell your story using videos not text) Include as many videos as possible.

Videos have a much higher level of engagement and viewing time and convey much more than you can ever
say with words.
Include at least one customer testimonial video on your app landing page.
Your client should speak specifically about the pains they had before and the benefits they gained after, not
product features. It should be all about your customers, not you.
Include one product demonstration video.
See the video best practices https://aka.ms/ReadyToGo.
Elements that reduce anxiety and risk, while increasing trust
EL EM EN T DESC RIP T IO N

Customer testimonials Don’t sell your product; let your customers do that for you.

Social proof is more credible and trustworthy to prospects. The purpose of testimonials is to reduce the
buyer's anxiety and fear.
Your testimonials should answer the following questions:
“Will this work for my situation?”
“What benefit will I really get if I buy this?”
“Is this going to be too hard?”
“How long is this going to take?"
“Can I trust this company?”

EL EM EN T DESC RIP T IO N EXA M P L E

Reduce risk Prospects are afraid of being scammed Source: Microsoft.com


and taken advantage of on the
internet. They're naturally cautious and
highly suspect.

You want to convert prospects to buyers.


Make it easy for them to buy, while reducing their anxiety. Transparency is the key to building trust.
Make sure that you include a link to a BUY NOW page, which includes full pricing details.
Give them a compelling offer they can't refuse. Offer a time-limited trial or special pricing discount if they
buy in 30 days.
Use scarcity to compel action. Offer a 100% money-back guarantee.
We recommend providing three offerings, optimized for three different customer segments. For more
recommendations on pricing, see the pricing guide located at https://mbspartner.microsoft.com/BFI/Topic/64

EL EM EN T DESC RIP T IO N

Live chat Include live chat, with a photo of one of your team members
smiling at an appropriate time to increase conversion, such
as when a prospect selects the back button on your pricing
page.

Include their name if possible to build trust.

Support elements: Interactivity and contact options


EL EM EN T DESC RIP T IO N

SHORT lead capture form Include a lead capture form on your page.

Only ask for their name and email address, you can get the rest later.
Your forms shouldn't have more than four or five fields to fill out. You haven't yet earned the right or enough
trust to ask for too much information at this point.
Most lead capture forms are way too long, demanding, and intimidating, and have low completion rates.
NOTE
Nobody has the time or is willing to fill out an annoying form, which is of no value to them, especially if it is purely self-
serving from your standpoint.

EL EM EN T DESC RIP T IO N

Contact Provide prospects with different contact options based on


their readiness to interact with you.

Ideally, include a phone number and an email address with an employee photo.
This alone could double your conversion rate.

EL EM EN T DESC RIP T IO N EXA M P L E

AppSource app page link & social Include a link back to your listing on Return to AppSource.
share AppSource, so the prospect can return
when ready.

Also, enable visitors to share and forward your app with others!

EL EM EN T DESC RIP T IO N

Close them! Add a get star ted button Include a specific call-to-action button with the option to
buy or try.
Embed App Overview
2/6/2023 • 4 minutes to read • Edit Online

Embed App is a term that defines an end-to-end solution meeting the specific needs of a vertical or micro-
vertical industry.
Dynamics 365 Business Central plays a vital role in the Embed App, as Business Central is embedded as an
integral part of the overall solution.
Some examples of an Embed App include:
A Dentist solution
A Real Estate Agent solution
A Food Processing solution
An Embed App refers to what is being provided to a given customer segment, unrelated to how the solution is
being implemented or architected. An Embed App can be built using AL, in other words extension, code-
customization, and a combination of extensions and code-customization.

Components
On a high level, an Embed App is a package that consists of the following parts:
Library extensions
This is the functionality of the Embed App that is implemented by the ISV partner in a form of extensions.
Third party extensions
These are add-on extensions coming from other ISVs that contribute to and enhance the Embed App. The
extensions are validated to be compatible by the Embed App owner.
Extended metadata
This includes additional Embed App properties that are specific to this type of app and not otherwise
available for other types of apps (see the list below).
Base application and tenant template (optional)
The following capabilities are only available for the Embed App and not for other types of Business Central apps
(Connect and Add-on).
Partner Branding
The Embed App will promote the partner's brand in several places:
Web Client and Web Service URLs
Client: https://[application name].bc.dynamics.com
Web Services: https://[application name].api.bc.dynamics.com
Name, image, and icon on the provisioning page of the Fixed Client Endpoint
Splash screen of the client
Title bar of the browser tab (for example, "Fabrikam Apples")
A dedicated product tile, icon, and short marketing description in the Dynamics shell
(https://home.dynamics.com)
In-product messages (such as pop-up errors, warnings, notifications)

Exclusivity
The partner can control which third party apps can be installed for their Embed App.
Safe listing of the 3rd party apps - no other apps will be possible to install, except the ones explicitly
approved by the partner
App install/uninstall controlled by the partner
The partner can choose to allow a customer to install other extensions from the AppSource, but this will be
an explicit partner decision, not the default behavior
Code -customizations of the base application
Partners can choose to bring their own code-customized base application as an Embed App for several reasons:
Shortening time-to-market ("lift and shift" approach).
The partner's current solution is a significantly customized version of the Dynamics NAV application and
it will require substantial time and effort to migrate it into extensions. A partner can lift their solution as-
is (upgraded to a supported platform) to Business Central service and start offering it to their new and
prospective customers. Then, they can gradually start moving their functionality into extensions to
achieve the benefits that come with the extension model. The earliest version of the Business Central
application you can bring to the service is version 16.
Usage of .NET interoperability and custom assemblies.
Partners that use .NET interoperability in their current application to address multiple business scenarios.
Although extensions today allow a number of these scenarios to be implemented in AL, they don't and
cannot cover for all possible scenarios of .NET usage. Therefore, the partner can choose to import the
required .NET add-ins into the Add-ins table of the base application, and these add-ins will automatically
be deployed into the environment where they will be running.
Additional settings (metadata)
An Embed App is the property of the partner, so the customers of the Embed App must be able to find the
partner's own legal, privacy, contact, community and feedback links (not Microsoft links) when they work
with the app:

Safe listed domains for embedding Embed App pages into other web sites, including SharePoint ("frame
ancestors")
Target version of Dynamics 365 Business Central platform
Target version of Dynamics 365 Business Central base application (if not included with the Embed App)
Azure KeyVault account for storing application secrets, such as accounts for connecting to 1-3rd party
services
Base application + tenant template. This is an optional component of an Embed App. The partner can
choose to include it or simply specify which version of the Dynamics 365 Business Central base
application the Embed App should use as a base application.
At this stage, within the extensions and base application, the partner can work in their own Object ID range.
Platform version availability
Microsoft is going to make new versions of the Business Central platform available to Embed App partners
through the Lifecycle Services portal (LCS). The partner will then have to pick the platform they want to use for
deployment of their solution.
Deploying versions
When a partner deploys a solution through the LCS portal, they can pick from the last three available versions of
the platform (minor and major). Every newly released minor or major platform update will be added to the list
and simultaneously one older version will be removed form that list.
Any existing deployments, running on platform versions that are older than 3 updates, will enter a grace period
of 30 days. And after that, if the deployment is not upgraded, it will be moved out of the standard SLA.

See Also
Microsoft Responsibilities
Qualification and Onboarding
Managing in Microsoft Lifecycle Services
Components and Capabilities
Deployment of Dynamics 365 Business Central
Administration of Business Central Online
Administration of Business Central On-Premises
Qualification and Onboarding of Partners to the
Embed App Program
2/6/2023 • 2 minutes to read • Edit Online

If you as a software development partner are interested in developing an app that meets the description of
Embed App in Embed App Overview, your app must meet qualification requirements. The main criteria for
Embed App onboarding at this point are:
Partner must provide all day, every day support. Their customers do not get to call Microsoft support. They
always call the partner.
Partner must live up to the standards for user assistance and documentation that are outlined in Dynamics
365 Business Central User Assistance Model. Good user assistance is part of Embed App success and uptake,
and it also lowers the work load on their support center.
Partner is committed to stay on the supported platform.
Partner provides an SLA for requests from Microsoft towards the partner
Partners must have a support agreement with Microsoft
Apps with a code-customized base application will have additional volume (number of users) requirements
associated with it.
When an Embed App is qualified for onboarding to Business Central online, the partner must provide the
following information about the Embed App to the Microsoft’s onboarding team:
The name of the application to be used for the client and web service URL. For example, an ISV for the
fabrikamapples app would provide the following information:
Client: https://fabrikamapples.bc.dynamics.com
Web Services: https://fabrikamapples.api.bc.dynamics.com
Entitlements for their application objects, per license type. For more information, see Licensing in
Dynamics 365 Business Central.
The rest of the information will be included with the Embed App package that the partner deploys through
LifeCycle Services.

See Also
Embed App Overview
Microsoft Responsibilities
Embed Apps Deployment
2/6/2023 • 2 minutes to read • Edit Online

This article provides an overview of the process for deploying an Embed App to the Business Central Online
service. The deployment involves the following tasks:

TA SK DESC RIP T IO N SEE. . .

Create a deployment package The deployment package is a .zip file Creating Deployment Packages for
that contains components required for Embed Apps
any Embed app, including:
ISV branding elements, like
images, icons, names, and so
on
An application database and
tenant template databases
A manifest-json file that
provides additional metadata
and deployment instructions.

Upload your apps to the App The apps are the individual extensions App Management API
Repository that make up your application. Apps
are delivered as .app files. You upload
your apps into the App Repository by
using the App Management API.

Upload the deployment package to Once you have the deployment Managing Embed Apps in Microsoft
Microsoft Lifecycle Services (LCS) package, and your apps have been Lifecycle Services
uploaded, you can deploy your
package to an LCS project.

See Also
Embed App Overview
Qualification and Onboarding
Managing Embed Apps in Microsoft Lifecycle Services
Creating Deployment Packages for Embed Apps
2/6/2023 • 13 minutes to read • Edit Online

To deploy an Embed App, you'll need a deployment package and your apps. This article describes how to create
a deployment package for an Embed App.
The apps are the individual extensions that make up your application. Apps are delivered as .app files, which you
upload to the App Repository via the App Management API. For information about this task, see App
Management API.
Once you've created the deployment package and uploaded your apps, you then upload the deployment
package to a registered project in Microsoft Lifecycle Services.

Deployment package overview


Creating a deployment package prepares the Embed app code and data for deployment on Business Central
Online service. The deployment package is a .zip file that contains components required for any Embed app.
At a high level, a deployment package consists of the following components:
ISV branding elements, like images, icons, names, and so on
An application database and tenant template databases as BACPAC files
A manifest-json file that provides additional metadata and deployment instructions
The deployment package has the following structure:

[FOLDER] branding/
- favicon.ico
- splash.png (or .gif)
- splash_narrow.png (or .gif)
- header.png (or .gif)

[FOLDER] databases/
- app.bacpac
- tenant.bacpac

manifest.json

The following sections explain how to build the deployment package.

Creating the database BACPACs using Docker


We strongly recommend you run Business Central on Docker using the BCContainerHelperPowerShell module
to prepare the BACPAC files.

IMPORTANT
You must only use the sandbox artifacts (Get-BcArtifactUrl -type sandbox) for your online deployments.

With the Docker container, you can:


Attach your own database and publish necessary extensions into the application database
Synchronize the schema of the tenant template database with the schema defined in the application
Ensure that all objects are compiled
Test your solution before creating the deployment package.
For more information about these and other things you can do, see BCContainerHelperPowerShell module.
About the databases
Business Central Online service runs exclusively in multi-tenant mode. Each customer environment is a separate
database, but sharing the same application. So the deployment package has to include two databases, which are
compiled into BACPAC format:
App.bacpac - includes the application database. The application database contains your application data, like
permissions, entitlements, report layouts, and so on.
Tenant.bacpac - includes the tenant template database, which may also contain initial tenant data.
Requirements for the application database

REQ UIREM EN T C O N DIT IO N DESC RIP T IO N

Running on a supported Business Always The Business Central platform is


Central platform updated monthly. You're responsible
for updating the Embed App to
operate with the updated version of
Business Central. The Embed App must
run on a supported build (platform) of
Business Central, namely, the current
version of Business Central or one of
the two immediately preceding
versions. The immediately preceding
versions can be both minor and major
versions of Business Central. Earlier
versions of Business Central platform
are out of support and can't be used
for Embed app deployments.

Unique Base Application ID, Name, and If any change is applied to the Create and assign your own unique
Publisher Microsoft Base Application objects App ID for it in the app.json file. Also,
change the Publisher property and the
Application name to your own in the
app.json file. You can't use the original
values of the Microsoft Base
Application unless you've extracted all
your customizations from that app
into your own app(s).

Use System Application Always Your Embed app must be built on top
of the Microsoft System Application.
The System Application must not be
customized and must be used as a
dependency for your customized or
non-customized Base Application.
REQ UIREM EN T C O N DIT IO N DESC RIP T IO N

Use Microsoft_Application.app file If you use customized Base Application Use Microsoft_Application.app to
encapsulate references to your own
customized Base Application, instead
of referencing that app as a direct
dependency in each extension
separately. This will also allow other
apps (like AppSource apps) to refer to
your solution via the
Microsoft_Application.app . For
more information about the
Microsoft_Application.app , see
The Microsoft_Application.app File.

Solution prefix or suffix Always Register a prefix or suffix to be used by


your solution. Apply the prefix or suffix
to all objects, while you're still
preparing your apps on-premise. The
prefix or suffix must be used for all
your app objects and also for your
tables, controls, fields, actions, and
groups that remain inside of
Microsoft's Base Application. There's no
need to apply this prefix or suffix to
Microsoft objects and fields in the
customized Base Application.

Fore more information about


requesting and using prefixes and
suffixes, see Benefits and Guidelines for
using a Prefix or Suffix.

Once your apps are deployed to


Business Central service, it won't be
possible to rename fields and objects,
because it would be a breaking
change. Breaking changes aren't
permitted in the online version of
Business Central. While still preparing
your apps on-prem, you can use the
Sync-NAVApp cmdlet with -Force
parameter to add prefix or suffix to
your objects and fields.
REQ UIREM EN T C O N DIT IO N DESC RIP T IO N

Entitlements Always It's important that the application


database also contains Microsoft
unmodified records in the following
tables:
Membership Entitlement
Entitlement Set
Entitlement

No users can sign in to your service if


these tables are empty. You can't add
new records or modify existing records
in these tables. For more information
about these tables, see Business
Central entitlements explained.

The entitlements can be copied from


the standard Business Central Demo
Database available in sandbox Docker
containers. Make sure you update the
entitlements when you uptake a new
version of Business Central application.
Consult the entitlements
documentation and parameters
provided for the
Clean-BCContainerDatabase and
New-BCContainer commands
included with the
BcContainerHelperPowerShell module.

Permissions Always The application database must contain


Microsoft unmodified records in the
following tables:
Permission Set
Permission

You can't modify the existing records in


these tables. If you need to add your
own permission sets and permissions
for the objects used by your own
solution, include these with your
extension instead. For more
information, see Exporting Permission
Sets.

Don't include customer-specific


permission sets and permissions in
your database, these permissions must
be added within the customer
environment instead. For more
information, see how to create or
modify a permission set in the
Business Central Application help.
REQ UIREM EN T C O N DIT IO N DESC RIP T IO N

Custom .NET add-ins If your solution uses custom .NET Import components into the Add-in
Server components (.NET add-ins) table in the application database. You
register the control add-ins, import
and manage the files by using the
New-NAVAddin cmdlet, Set-NAVAddin
cmdlet, Get-NAVAddin, or Remove-
NAVAddin cmdlets from the Business
Central Administration Shell.

IMPORTANT Using custom .NET


Server components option is being
deprecated. So refactor your code to
remove custom .NET components as
soon as you can. For example, use
Azure Functions instead.

Requirements to the tenant template database


While you are testing your Embed app solution in a Docker container, you can publish and install all the apps
you need for your customers. When you're done testing, we recommend you to uninstall (including removing
the data) and unpublish all apps, including Microsoft apps, before you export the application and tenant
template databases.
Instead of keeping the apps pre-published and pre-installed in your databases, they must be uploaded to the
service by using the App Management API and listed in the [apps] section of the manifest.json file. This way
the apps will be automatically published and installed later, during deployment, following the list you provide in
the manifest.json file that you include with your deployment package.
We recommend you to use RapidStart packages to populate the new companies with the demo data or initial
setup data.

Exporting application and tenant databases


You export the databases to BACPACformat by usingthe Export-BCContainerDatabasesAsBacpac command from
the BcContainerHelperPowerShell module.
We strongly recommend using this command for creating the BACPAC files you're planning to deploy to the
Business Central service. To simplify exporting the data, the command also does a number of clean-up stepson
the databases. It cleans up sessions,database connection, list of tenants, imported license, and more. It also
verifies that the schemas of the application and tenant databases are synchronized, which is essential for
deployment.We keep enhancing this commandwith more cleanup and validation steps as we discover BACPAC-
related issues with deployments. So, remember to update the BcContainerHelperPowerShell module for every
new iteration.

Providing deployment instructions in the manifest.json


The manifest.json file, supplied within the deployment package, contains important properties used by the
deployment routine to configure the application version according to the Embed app ISV requirements.

SET T IN G TYPE DESC RIP T IO N

manifestSchemaVersion String, <major>.<minor> Schema version of the manifest.


Current manifest schema version is
3.0.
SET T IN G TYPE DESC RIP T IO N

id GUID Unique ID of the Embed solution. Used


for informational purposes, not used in
the runtime. As a best practice it's
recommended to use the Id of your
main app in this field.

name String Short marketing name of the app.


Used for informational purposes, not
used in the runtime.

description String Short marketing description of the


app. Used for informational purposes,
not used in the runtime.

publisher String Name of the ISV organization that


owns the Embed app. Used for
informational purposes, not used in
the runtime.

version String. Version of the deployment package


<major>.<minor>.<build>. being uploaded. This version is
<revision> displayed in the Application Version list
in LCS, it has no other purpose or
application in the runtime. Remember
to update this version for every new
deployment, so you can distinguish
the deployments in the LCS UI.

branding Object Object that contains paths to the


branding elements of the ISV included
with the deployment package. See the
"branding" section below.

databases Object Object that contains paths to the


application and tenant template
BACPAC files of the ISV solution
included with the deployment package.
See the "databases" section below.

links Object Object that contains paths to various


URLs to be used in the Business
Central Web Client. See the "links"
section below.

apps Array Array that contains the list of apps and


their dependencies, which are
uploaded by the ISV via the App
Management API. See the "apps"
section below.

"branding"

SET T IN G TYPE DESC RIP T IO N


SET T IN G TYPE DESC RIP T IO N

productName String Official marketing name of your Embed


app. This name will be displayed in the
title bar of the Business Central Web
Client.

productNameShort String Short version of Embed app marketing


name. It's displayed in the areas of the
UI where full Product Name can't be
displayed.

marketingName String Longer (full) marketing name of your


Embed app.

images Object Object that contains paths to the


branding images included with the
package. See the "images" section
below.

"images"

IMPORTANT
The combined size of all images you include with the deployment package must not exceed 490 KB.

SET T IN G TYPE DESC RIP T IO N

appleTouchIconPath String Format: PNG. Dimensions: 114x114

faviconPath String Format: ICO. Dimensions 16x16,


32x32, 48x48 & 64x64. Used on the
Browser tab and bookmark icon.

headerPath String Formats: PNG, GIF. Dimensions:


558x107. Displayed on "Minimal
Layout" pages, like the Microsoft Office
add-in sign-in; Authentication /
Permission errors ("You don't have
access to Business Central", "You've
successfully signed out.")

splashLandscapePath String Formats: PNG, GIF. Dimensions:


2048x272. Splash screen on devices
with large screen space, for example,
full screen browser, tablet in landscape
mode.

splashPortraitPath String Formats: PNG, GIF. Dimensions:


960x320. Splash screen on devices
with limited screen space, for example,
small browser, phones, tablets in
portrait orientation.

"databases"
SET T IN G TYPE DESC RIP T IO N

applicationBacpacPath String Path to the application database


(.bacpac) included with the deployment
package.

tenantTemplateBacpacPath String Path to the tenant template database


(.bacpac) included with the deployment
package.

"links"

SET T IN G TYPE DESC RIP T IO N

baseHelpUrl String Link to your online Help server or web


page.

baseHelpSearchUrl String Link to your online Help server or web


page.

communityUrl String Link to your community blog page.

feedbackUrl String Link to your product feedback page.

legalUrl String Link to your product legal and privacy


terms.

signInHelpUrl String Link to your sign-in help URL.

comingSoonUrl String Link to your product announcements


page.

blogUrl String Link to your product blog page.

contactSalesUrl String Link to your sales page.

"apps"
This section of the manifest.json file must list all the apps used by your solution and their dependencies. Even if
the dependency app belongs to a different publisher, for example Microsoft, you must include it. This list will be
used by the deployment routine to publish and install these apps to your service and for your environments.

SET T IN G TYPE DESC RIP T IO N

id String Unique ID of the app. Use the same Id


as listed in the app.json file.

name String Name of the app. Use the same Name


as listed in the app.json file.

publisher String Name of the ISV organization that


owns the app. Use the same Publisher
as listed in the app.json file.
SET T IN G TYPE DESC RIP T IO N

initialVersion String Minimum required and compatible


version of the app.

If "allowedUpdates" is set to
"none" , then the exact version of the
app you specify must be available in
the App Repository. In this case, a full
initial version number must be
specified.

For other "allowedUpdates" values,


it's enough that an app with a higher
or equal [build].[revision] part of the
version is available in the App
Repository. You don't need to specify a
full version number -- [major].[minor]
and [major].[minor].[revision] are also
accepted. This applies to the App
versions uploaded either by you or by
other publishers who own the apps.
SET T IN G TYPE DESC RIP T IO N

allowedUpdates Enum Allowed values: none, hotfix, minor, all.

You can set up rules that determine


which app version to use for the new
signups. You can also specify whether
updating of the installed app is
allowed.
"none" : It won't be possible
to apply any new versions to
this app inline (only side by
side). Only the application
version that exactly matches
the specified initial version
number will be used for the
new signups.
"hotfix" : You allow hot fixing
this app with newer hotfix
versions, that is, versions with a
higher build and revision
numbers than in the
"initialVersion" , but with
the same major and minor
version. New signups and
environments you upgrade to
this deployment will
automatically get the latest
available hotfix version of the
app installed.
"minor" : Customers can view
and install newer applicable
minor (or hotfix) versions of the
app via the Business Central
Administration Center. New
signups and environments that
you upgrade to this
deployment will automatically
get the latest available hotfix
version of the app installed.
Minor updates won't be
automatically installed. They
must be installed by the newly
signed-up customers using the
Business Central Administration
Center.
"all" : Customers can view
and install all newer applicable
versions of the app via the
Business Central Administration
Center. New signups and
environments that you
upgrade to this deployment will
automatically get the latest
available hotfix version of the
app installed.

blockUninstall Boolean Allow or disallow the app to be


uninstalled using the Extension
Management page.
SET T IN G TYPE DESC RIP T IO N

publishOnly Boolean Specifies whether to only publish (


true ) that app to the service.
Customers can then install it manually
from the Extension Management page.
If false , the app is automatically
installed for all new environments and
environments updated to this
deployment.

IMPORTANT Dependencies of an app


with "publishOnly": "false" must
also be marked with
"publishOnly": "false" , otherwise
the app that depends on them will fail
to be installed.

Sample manifest
Sample of the manifest.json file.

{
"manifestSchemaVersion":"3.0",
"id": "201e5067-99cc-4974-900a-b50bd4fbe777",
"name": "Fabrikam Rentals",
"description": "Harness the power of the most feature-rich office furniture rentals solution from
Fabrikam.",
"publisher": "Fabrikam",
"version": "16.1.50043.50321",
"branding": {
"productName": "Fabrikam Rentals",
"productNameShort": "Rentals",
"marketingName": "Fabrikam Rentals",
"images": {
"appleTouchIconPath": "branding/appletouch.ico",
"faviconPath": "branding/favicon.ico",
"headerPath": "branding/header.png",
"splashLandscapePath": "branding/web-wide.png",
"splashPortraitPath": "branding/web-narrow.png"
}
},
"databases": {
"applicationBacpacPath": "databases/app.bacpac",
"tenantTemplateBacpacPath": "databases/tenant.bacpac"
},
"links": {
"baseHelpUrl": "https://help.fabrikam.com/help/",
"baseHelpSearchUrl": "https://help.fabrikam.com/help/",
"communityUrl": "https://fabrikam.com/au/contact",
"feedbackUrl": "https://fabrikam.com/au/contact",
"legalUrl": "https://fabrikam.com/au/legal",
"privacyUrl": "https://fabrikam.com/au/privacy",
"signInHelpUrl": "https://fabrikam.com/au/contact",
"comingSoonUrl": "https://go.microsoft.com/fwlink/?linkid=2047422",
"blogUrl": "https://go.microsoft.com/fwlink/?linkid=2076643",
"contactSalesUrl": "https://go.microsoft.com/fwlink/?linkid=828707"
},
"apps": [
{
"id": "63ca2fa4-4f03-4f2b-a480-172fef340d3f",
"initialVersion": "16.1",
"name": "System Application",
"publisher": "Microsoft",
"allowedUpdates":"hotfix",
"publishOnly": false,
"publishOnly": false,
"blockUninstall": true
},
{
"id": "6d4391a2-9cae-41e9-a270-136af8acfbc7",
"initialVersion": "16.1.5",
"name": "Fabrikam Rentals Add-on",
"publisher": "Fabrikam",
"allowedUpdates":"minor",
"publishOnly": false,
"blockUninstall": true
},
{
"id": "201e5067-99cc-4974-900a-b50bd4fbe777",
"initialVersion": "16.1.50043.50321",
"name": "Fabrikam Rentals",
"publisher": "Fabrikam",
"allowedUpdates":"minor",
"publishOnly": false,
"blockUninstall": true
}
]
}

Creating the deployment package zip file


After you have all the components of the deployment package ready, you can package them into a .zip archive.
The deployment package (.zip) can't include any additional subfolders and files and must have the following
structure:

[FOLDER] branding/
- favicon.ico
- splash.png (or .gif)
- splash_narrow.png (or .gif)
- header.png (or .gif)

[FOLDER] databases/
- app.bacpac
- tenant.bacpac

manifest.json

Now, you can deploy your package to Business Central Online service. See Managing Embed Apps in Microsoft
Lifecycle Services for more information.

See Also
Embed App Overview Qualification and Onboarding Managing Embed Apps in Microsoft Lifecycle Services
Managing an Business Central Embed App in
Microsoft Lifecycle Services
2/6/2023 • 7 minutes to read • Edit Online

Microsoft provides essential functionality within Microsoft Lifecycle Services collaboration portal (LCS) to
support qualified ISVs in managing the Embed App based on Business Central online.

Creating LCS project


In LCS, you should create a project for each Embed App and each country you would like to deploy to Business
Central service. You provide the list of countries where you want to run your Embed app during onboarding. You
can only deploy your solution to the country that is already supported in the Business Central online service.
Find the list of supported countries here: https://aka.ms/bccountries.
Before you can create a project, you need to unlock a corresponding Private Preview feature. Once you sign in to
LCS, select the Preview feature management action. Then on the Preview feature management page, select
the "+" action to add a new preview feature using a preview code. In the Preview code field, enter the code you
received from Microsoft during onboarding. You should now see the "Microsoft Dynamics 365 Business Central
(SaaS)" feature on the list of the private preview features on this page.

IMPORTANT
Even though the project will be created by one user, every user you are planning to add to your LCS project will have to
activate the "Microsoft Dynamics 365 Business Central (SaaS)" feature using the same preview code you received from
Microsoft. Without this activation, the users you add to your LCS project will run into permissions issues when trying to
open the LCS project that you created.

Navigate back to the main page and start creating a new project by selecting the "+" action. Choose Migrate,
create solutions, and learn category as the purpose of the project. On the next page, provide the project
name.

NOTE
You will have to create a separate project for each country, even if your Embed app is going to be exactly the same.
Therefore we recommend that you use the name of your Embed app appended by the country code as the name of your
project, for example "Fabrikam Rentals, DK", "Fabrikam Rentals, US" and so on.

Next, provide a short description for your project (optional), select Microsoft Dynamics NAV as the product
name and Microsoft Dynamics 365 Business Central (SaaS) as the product version. Select the Create
button to complete creation of the project.
After you create the project, send its ID to the e-mail alias specified on the main project page for safe listing
purposes. You can find the project ID in the URL displayed in your browser, such as
https://lcs.dynamics.com/V2/NavProjectDashboard/[projectID]

Once your LCS project ID has been safe listed by Microsoft, you can start performing deployments of your
solution to Business Central service.

Deploying the Embed App


Prerequisites
Before deploying the Embed App, complete the following tasks:
1. Create the deployment package for the Embed App.
The deployment package is a .zip file that contains components required for any Embed app. For more
information, see Creating Deployment Packages for Embed Apps.
2. Upload your apps into the App Repository
Upload new versions of your own apps into the App Repository using the App Management API. Don't
upload Microsoft apps or apps from other ISVs. The Microsoft team regularly uploads Microsoft apps and
AppSource apps to this repository, so you don't have to. For more information, see App Management API.
Upload the deployment package
Once you have the deployment package and uploaded the apps, you can upload the Embed App deployment
package into the Asset librar y within your LCS project.
1. In your LCS project, select the Asset librar y action to navigate to the Asset library page.
2. Select the + action to open the Upload Software deployable package file wizard.
3. Provide the Name and Description (optional) for your package.
The asset name you provide will be displayed on the Application Version list inside your project.
4. Select the Add the file action to select and upload the deployment package.
5. Wait for the package to get uploaded, then select the Confirm button to close the upload wizard.
Start the Embed App deployment
Now, start deploying the package you uploaded in the Asset librar y by doing the following steps:
1. Go to the Rings section of your project.
2. Select Maintain menu, then select Deploy action to open the Deploy package wizard.
3. Select the package you want to deploy in the Package name field.
4. Select the Target platform , then select Deploy button to start the deployment.
The deployment routine will pull the apps that are listed in the [apps] section of the manifest.json file in your
deployment package from the App Repository. It will then publish and install the apps based on the instructions
you provided in the manifest.json file.
After the environment is successfully provisioned, its status on the list of application versions will be set to
Deployed . To allow sign-ups to be directed to this application version, you select the Use for new tenants
check box. You can only have one application version marked this way at a time.

IMPORTANT
The Business Central platform is updated monthly. You are responsible for updating the Embed App to operate with the
updated version of Business Central. The Embed App must run on a supported build of Business Central, for example, the
current version of Business Central or one of the two immediately preceding versions. The immediately preceding versions
can be both minor and major versions of Business Central. The list of supported versions is displayed in the LCS portal on
the Deploy package wizard in the Target platform field. The versions, which aren't displayed on that list are out of
support. You customers running on these versions can't be serviced at the service levels set forth in the published Service
Level Agreement.

Onboarding customers and creating environments


Partners who support an Embed App based on Business Central online can onboard customers in two ways:
Using the self-service IW sign-up – for acquiring a free evaluation version of the app.
Through the Microsoft Partner Center Cloud Solution Provider (CSP) program by contacting the partner - for
acquiring a paid production version of the Embed App.
Tenant provisioning is happening automatically ( just-in-time) on the first attempt to sign in to the solution.
Navigating to https://businesscentral.dynamics.com will trigger provisioning of the Business Central tenant,
while navigating to https://[application name].bc.dynamics.com will trigger provisioning of the tenant running
on the application name application.
Self-Service (IW) sign-up - evaluation
The Embed App partner can choose to allow customers to use a self-service sign-up (also known as IW sign-up
and viral sign-up) for their Embed App. In that case, the partner must prepare a sign-up URL that will redirect
the Microsoft 365 sign-up flow to their application URL. The sign-up URL must have the following format:
https://signup.microsoft.com/signup?sku=6a4a1628-9b9a-424d-bed5-4118f0ede3fd&ru=https%3A%2F%2F[application
name].bc.dynamics.com%2F%3FredirectedFromSignup%3D1

The partner can then pass the URL to their customers, either from the partner's own marketing page or in a
welcome e-mail, for example.
To work with an Embed App, the customers would use a URL that looks something like this:
Client: https://[application name].bc.dynamics.com
Web Services: https://[application name].api.bc.dynamics.com
In contrast, to work with Business Central, they would use these URLs:
Client: https://businesscentral.dynamics.com
Web Services: https://api.businesscentral.dynamics.com

Once you've established the reseller relationship with the customer and added Business Central subscriptions
with required number of licenses for them, you must use your own branded Embed app URL to sign in their
environment and Business Central Administration center.
To create a new production environment for your customers, go to this URL:

https://[your application family].bc.dynamics.com/[Customer's Azure AD Tenant ID]/Production

To open your customer's Business Central Administration center, go to this URL:

https://[your application family].bc.dynamics.com/[Customer's Azure AD Tenant ID]/admin

Each environment that you signed up for the Embed App is then displayed on the Tenant list part in your LCS
project. On this part, you can find more details about the environment, including the name and the URL to sign
in to each one. You can see which environments are running on which application version by selecting
application version on the list.

Monitoring the Embed app


In the LCS portal, you get access to various logs for the activities that you do in the portal:
Deployment: logs of deployment of the application versions
Tenant provisioning: logs of creation of the new customer environments
Tenant upgrades: logs of customer environments upgrades
Application errors: errors that are displayed to the customers when they work with the Embed app
functionality
To get to these logs, in the Rings section of your project, select Maintain menu and then select Monitor action.
On the Ring monitoring page, first select the Categor y , depending on the operation for which you want to
retrieve the logs. Then set the Period (min) field to the number of minutes back in time, for which you want to
see the logs. Don't use the All category.

NOTE
The logs typically appear in LCS with a delay of 15 minutes.

For easier troubleshooting, we recommend exporting the logs to a CSV file, using Expor t to CSV action, and
then analyzing them in Microsoft Excel instead.
It's important to always review the logs before submitting any issues to Microsoft. When reporting issues, attach
the relevant logs in TXT or CSV format, don't use screenshots.

See Also
Embed App Overview
Licensing in Dynamics 365 Business Central
Components and Capabilities
Microsoft Responsibilities for Apps on Business Central online
Preparing Demonstration Environments of Dynamics 365 Business Central
Preparing Test Environments of Dynamics 365 Business Central
Using Application Family in Embed App
2/6/2023 • 2 minutes to read • Edit Online

Business Central service is a part of rich ecosystem of surrounding applications and services. One of the
prominent Embed App capabilities is to promote and use the ISV brand in various places of the overall service
experience.
During onboarding, the ISV provides the application family name. The application family helps identify their
solution among other Business Central apps and Embed App's of other ISVs.
The following table describes different aspects of using the application family when interacting with Business
Central components and surrounding services.

H O W TO USE W IT H T H E EM B ED
A REA A P P L IC AT IO N FA M ILY A DDIT IO N A L DETA IL S

Business Central Web client Use the application family in the URL: Web Client URL

[application
family].bc.dynamics.com

Business Central web services Use the application family in the URL: Introduction to automation APIs

[application
family].api.bc.dynamics.com

Business Central mobile app Use the application family in the URL: Getting Business Central on Your
Mobile Device
ms-
businesscentral://[application
family].bc.dynamics.com/

Business Central administration center Application family is displayed for each The Business Central Administration
environment Center

In-code URL generation (GETURL) GETURL returns the branded endpoint, GetUrl Method
including the application family.

Development endpoint for Visual To publish and debug apps in a JSON Files
Studio Code Sandbox environment, use the
"applicationFamily" property in the
launch.json file

Microsoft AppSource To install AppSource apps, use the Installing apps by selecting a direct
branded URL with the following app link in AppSource (for example,
parameters: "Get it now" or "Free trial") isn't
supported. This action redirects to the
https://[application standard Business Central URL.
family].bc.dynamics.com/[TenantID]/?
noSignUpCheck=1&filter=%27ID%27%20IS%20%27[AppID]%27&page=2503

Microsoft Power BI Supported for connecting to the Enabling Your Business Data for Power
environment data from Power BI and BI
embedding Power BI pages in the
Business Central Web client.
H O W TO USE W IT H T H E EM B ED
A REA A P P L IC AT IO N FA M ILY A DDIT IO N A L DETA IL S

Outlook Add-in Not supported Using Business Central as your


Business Inbox in Outlook

Excel Add-in Supported Setting up the Excel Add-In for Editing


Business Central Data

CDS integration Supported Integrating with Microsoft Dataverse

Power Automate, Power Apps, Logic Business Central standard connector Custom connector FAQ for Azure Logic
apps currently can't be used (support is Apps, Power Automate, and Power
coming soon). The ISV needs to build a Apps
custom connector. The custom
connector is required anyway, also for
the Business Central environments, if
you want to include data from other
tables that aren't included with the
standard Business Central connector.

Cloud Migration Tool Supported Migrating On-Premises Data to


Business Central Online

See Also
Embed App Overview
Licensing in Dynamics 365 Business Central
Components and Capabilities
Microsoft Responsibilities for Apps on Business Central online
Preparing Demonstration Environments of Dynamics 365 Business Central
Preparing Test Environments of Dynamics 365 Business Central
Application Access Management for the Embed
App
2/6/2023 • 4 minutes to read • Edit Online

In this article, you'll learn how you can control which customers can create online environments based on your
Embed App application family, by enabling your resellers (VARS) to use the Application Management API.

Overview
Both Business Central and Embed Apps are distributed by Cloud Solution Provider (CSP) resellers. Embed Apps
use standard Business Central licenses—the same licenses used for Business Central. So any reseller who sells
Business Central can also create online environments that run on your Embed App by default.
As an Embed App owner, you'll want to control which customers and which resellers can create online
environments based on your Embed App application. You'd also like to allow these resellers to control whether
customers have access to both Business Central and your Embed App or only to the Embed App.
To support these capabilities, two features are available, depending on your role:

RO L E W H AT Y O U C A N DO

Embed App ISV Enable application access management for all environments
in your LCS project.

Register VARs to give them access to the Application Access


Management API.

VAR Once you've been registered by the Embed App ISV, you can
allow or block access to the Embed App or Business Central
app for specific customers.

Embed App ISV: Enable application access management and register


VARs
Follow these steps to provide your VARs with access to the Application Access Management API. Once they have
access, they can use the API to enable or disable the creation of online environments based on your Embed App
application.
Preparation
Prepare the VAR for the change
Once you enable application access management in your LCS project, any existing customers already
using your Embed App will be blocked from access to their Embed App environments by default. It also
won't be possible to create new environments based on your Embed App application for any new or
existing customers. The VAR will have to explicitly enable the access for each customer by using the API
explained in the section below.Make sure you coordinate this change with your VARs.
Get the VAR's CSP organizational ID (Microsoft ID). You'll need this ID for registration.
The VAR can find their Microsoft ID in Partner Center, on the Account Settings > Organizational
profile page.
Enable application access management and register VARs
1. Go to Lifecycle Services and open your project.
2. Select the Manage VARs tile.
3. On the Manage VARs access page, specify if VARs must be able to approve customers.

IMPORTANT
This step enables application access management. Once you have allowed VARs to approve customers, it won't
take effect until you save the change. Be aware that once you save, any existing VAR customers already using your
Embed App and any new customers will be blocked from access by default, until the VAR explicitly enables the app
for them.

4. Now you start to register VARs. Select +Add .


5. On the Register new VAR Tenant , enter the VAR's Microsoft ID in the Tenant ID box.
6. Enter a description in the Description box to make it easier for you to identify the VAR.
7. Select Add .
8. Select Save when done.
Once a VAR is registered, they can start to enable and disable the Embed App for their customers using the
Application Management API.
Disabling and enabling application access management
In your LCS project, you can specify that VARs can or cannot approve customers without having to remove VARs
from the list. This capability is useful if you need to temporarily allow access to all VARs and all customers. For
example, suppose a VAR is registered but they're not ready to use the API yet.

IMPORTANT
If you specify that VARs cannot approve customers, even if the VARs are still listed on the Manage VARs access page,
the environment access settings made by VARs for their customers will be ignored. The existing access settings will be
enforced again once you allow the VARs to approve customers again and save the changes.

VAR: Manage customer access to the Embed App environments


As a VAR, once you've been registered by your ISV, you must explicitly give every customer access to create
Embed App environments. Access is given by using the application access management API. The required steps
are outlined in the sections that follow.
Prerequisite: Register an application for in your Azure Active Directory tenant
You only have to do this step once. In your Azure Active Directory (Azure AD) tenant, register an application that
has delegated permission to the Dynamics 365 Business Central API. You'll use this application to call
theBusiness Central Administration Center APIfor each customerthat you want to onboard.
Apart from registering an application, you'll also need an access token. For more information, see Setting up
Azure Active Directory (AAD) based authentication and Getting an access token.
Onboarding customers
With application access management enabled, the typical process for getting customers up and running on a
Embed App environment is as follows:
1. Connect with the customer using Partner Center:
a. Establish reseller relationship with the customer
b. Add necessary Business Central subscriptions
c. Assign Business Central licenses to the customer users.
For more information, see Connect with customers.
2. Control access to Embed App and Business Central application using the application access management
API:
a. Enable the customer to create environments based on the Embed App
b. Block the customer from creating environments based on the Business Central application.
For more information, see Application Access Management API. The article explains the API calls that you
can make to get the list oftheavailable Embed Apps and enable or disable a specific Embed Appfor the
customer.
This work is done using your AAD application and delegated admin access and credentials.
3. Create the first Embed App environment for the customer by signing in to it for the first time, using the
branded Embed App URL:
https://[application family].bc.dynamics.com/[Customer Azure Active Directory Tenant ID]/Production

See Also
Application Access Management API
Using Application Family Managing an Business Central Embed App in Microsoft Lifecycle Services
Application Access Management API
2/6/2023 • 2 minutes to read • Edit Online

As a Delegated Global Administrator or as a Delegated Dynamics 365 Administrator , you can manage
access to application families available in the service. The application family is Business Central or Embed App
applications that may be provisioned through the service.

NOTE
This API endpoint can only be used by Delegated Users. Service-to-service authentication using an AAD App authorized
in the Business Central administration center is not supported.

You can get the list of applications that are available to the customer tenant. From this list you can determine, by
setting the access property, for which applications an environment may be created on the tenant.

Get List Of Manageable Applications


Returns a list of manageable applications by family and country code.

GET /admin/v2.15/manageableapplications

Response
Returns a wrapped array of applications.

{
"value": [
{
"applicationFamily": string, // The name of the family for a given Business Central offered
application. (Typically this will just be "BusinessCentral")
"access": boolean, // Indicates if the tenant has access to the application family/country code
combination
"countryCode": string, // The country code of the application.
}
]
}

Example (PowerShell)

$url = "https://api.businesscentral.dynamics.com/admin/v2.3"
$result = Invoke-WebRequest -Uri "$($url)/manageableapplications" -Headers @{"Authorization" = "Bearer
$token"} | ConvertFrom-Json
Write-Host $($result.value | ConvertTo-Json)

Control the access to Applications


Pass the application family name in the URL and a boolean in the body.
True - enables the access.
False - disables the access.
Content-Type: application/json
PUT /admin/v2.15/manageableapplications/{applicationFamily}/countries/{countryCode}

Route Parameters
applicationFamily - The name of the family for a given Business Central offered application. (Typically this value
will just be "BusinessCentral")
countryCode - Country code for the targeted application.
Body

{
<boolean> // Desired access state
}

NOTE
It is not possible to disable the access to an application family for the AAD tenant which already has an environment
created in that family.

Expected Error Codes


invalidInput - the targeted property in invalid in some way
target: {targeted tenant's AAD Id} - attempt to remove access to an application but the targeted tenant
already has an environment in that application
resourceDoesNotExist - couldn't find the targeted application
Example (PowerShell)

$url = "https://api.businesscentral.dynamics.com/admin/v2.3"
$country = 'DK'
$applicationFamily = 'frentals'
$access = "true"
Invoke-WebRequest -Uri "$($url)/manageableapplications/$($applicationFamily)/countries/$($country)" -
Headers @{"Authorization" = "Bearer $token"} -Body $access -Method Put -ContentType "application/json"

See Also
Application Access Management
Using Application Family
App Management for ISVs
2/6/2023 • 2 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1

Each Business Central environment is built as a collection of apps. These apps include Microsoft apps and apps
from AppSource that reselling partners have installed for customers. The apps are working together to provide
customers with a broad set of features to address their various business, market, and industry needs.
As an authorized ISV, you can deliver your functionality or your services as apps in AppSource. For more
information, see Get Started with Building Apps. To help you manage your apps running in different customer
Business Central environments, Business Central provides the App Management API.

About the App Management API


The App Management API is a REST-based API. It requires that you're an authorized ISV and your apps have
been registered by Microsoft. Once registered, you access the API by using this global endpoint:
https://apps.businesscentral.dynamics.com.
You can use the API for the following operations:
Make major, minor, and hotfix app updates available to customers for installation from the Business
Central administration center.
You make the updates available by uploading them to the App Repository. The new app versions will then
be available on Manage Apps page of the Business Central administration.
Retrieve the list of the customers' environments that have your app installed.
Schedule the automatic deployment of the app hotfixes for their customers' environments.
The App Management API lets you apply modern continuous integration (CI), continuous deployment (CD), and
DevOps practices to your work, for example:
Automate operations by using AL-Go for GitHub .
Organize role-based access control.
Manage your apps at scale, in multiple geo locations, supported by advanced and well-controlled build, test,
and release flows.
For more information about the API, see App Management API.

NOTE
Currently, direct access to the API is only available for the ISVs working with the Embed apps; not Add-on and Connect
apps. To manage versions of Add-on and Connect apps, you use Partner Center to upload the new app versions to
Business Central offers. The apps will undergo a technical and marketing validation before becoming available on
AppSource. After passing validation, the new versions are made available in Business Central administration center to the
customers that have these apps installed.

Legal information
The apps that are stored in the App Repository are governed by the Microsoft Publisher Agreement. For more
information, see Publishing your business application.
The App Management API is governed by Microsoft APIs Terms of Use. For more information, see Microsoft APIs
Terms of Use

See Also
Manage Apps in the Business Central Administration Center
App Management API
2/6/2023 • 13 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1

Entities
App
Description
The app entity represents a Business Central App that has been registered with the service and so it can be
managed via the API. The app entity contains some basic metadata about the app, such as:
its ID
the Azure Active Directory Tenant ID of the publisher's organization
which Azure location the respective .app files and other metadata should be stored in.

NOTE
An app doesn't refer to any specific .app file or version of the app.

Properties
NAME DESC RIP T IO N SC H EM A

ID The ID of the app. The ID must remain string (uuid)


the same across all app versions.

publisher The publisher's name. string

publisherAadTenantId The ID of the Azure Active Directory string (uuid)


tenant that represents the publisher's
organization.

publisherContactEmail The publisher's contact e-mail address. string

storageLocation The Azure location in which data string


related to this app should be stored.

_etag The entity tag that contains a value string


unique to the entity's current state.

Available Endpoints
List apps
Lists all apps that match the provided (optional) filter that the current principal can access.

GET https://apps.businesscentral.dynamics.com/v1.0/apps?$filter=<odata_filter>
Parameters

TYPE NAME DESC RIP T IO N SC H EM A

query $filter Restricts the set of items OData filter


returned.

Example Request

GET https://apps.businesscentral.dynamics.com/v1.0/apps?$filter=storageLocation eq 'West Europe'

Example Response

{
"value": [
{
"id": "36d697e1-1982-43a5-9927-7f8f2a3eb361",
"publisher": "Contoso",
"publisherAadTenantId": "49cf52d4-fc10-41af-91ab-2d7cd011db47",
"publisherContactEmail": "publisher@contoso.com",
"storageLocation": "West Europe",
"_etag": "5c47bfb0-d80c-4780-99ed-c3a3d38ac539"
}
]
}

Country
The country entity represents a country that an app is available in.
A country is represented by its ISO 3166-1 alpha-2 (2-letter) country code.
Specific versions of Business Central Apps can be made available for specific countries.
Properties
NAME DESC RIP T IO N SC H EM A

countr yCode The ISO 3166-1 alpha-2 (2-letter) string


code for the country.

_etag The entity tag that contains a value string


unique to the entity's current state.

Available Endpoints
List countries
Lists all countries the specified app has been made available in.

GET https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app to list the string (uuid)


countries for.

Example Request
GET https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-f10f36a2e213/countries

Example Response

{
"value": [
{
"countryCode": "US",
"_etag": "f6039211-0dea-481a-80a5-38498dcea011"
},
{
"countryCode": "DK",
"_etag": "bb8f8166-a6cc-4562-b135-0b13257b032f"
}
]
}

Get country
Gets the country with the specified country code in the specified app .

GET https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app that the string (uuid)


country belongs to.

path countryCode The ISO 3166-1 alpha-2 (2- string


letter) code of the country.

Example Request

GET https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-f10f36a2e213/countries/US

Example Response

{
"countryCode": "US",
"_etag": "f6039211-0dea-481a-80a5-38498dcea011"
}

Add or update country


Adds a new country to the specified app or updates an existing one.

PATCH https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app that the string (uuid)


country belongs to.
TYPE NAME DESC RIP T IO N SC H EM A

path countryCode The ISO 3166-1 alpha-2 (2- string


letter) code of the country
to add.

body country The country properties that Country


should be added or
updated.

Example Request

PATCH https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-f10f36a2e213/countries/AT

{
"countryCode": "AT"
}

Example Response

{
"countryCode": "AT",
"_etag": "584915f0-6319-4aab-a23c-743c0c4d9aeb"
}

Principal
Description
The principal entity represents an Azure Active Directory user or application that has some level of access to
an app .
Principal can have different roles that determine which actions they're allowed to do. The currently supported
roles are:
- Owners are allowed to do all available actions on all entities.
Owner
Contributor - Contributors have similar permissions to owners, except that they aren't allowed to
add/update principals.
Reader - Readers can read information about the various entities, but can't add/update anything.

Properties
NAME DESC RIP T IO N SC H EM A

aadTenantId The ID of the Azure Active Directory string (uuid)


Tenant the principal belongs to.

id The ID of Azure Active Directory string (uuid)


user/application.

roles The list of roles the principal has string[]


assigned.

type The principal type. enum (User, Application)


NAME DESC RIP T IO N SC H EM A

_etag The entity tag that contains a value string


unique to the entity's current state.

Available Endpoints
List principals
Lists all principal s that match the provided filter within the specified app .

GET https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/principals?$filter=<odata_filter>

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app to list the string (uuid)


principals for.

query $filter Restricts the set of items OData filter


returned.

Example Request

GET https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-f10f36a2e213/principals?
$filter=type eq 'User' and 'Owner' in roles

Example Response

{
"value": [
{
"id": "c07b7af3-8c9a-4bb1-9a0b-03692ba98d6d",
"type": "User",
"aadTenantId": "0c1cbce0-b823-4acf-be2f-1ac3a4e81c21",
"roles": [
"Owner"
],
"_etag": "c99541ab-a0d2-4807-86f8-e1eb1853eb4f"
}
]
}

Get principal by ID
Gets the principal with the specified ID in the specified app .

GET https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/principals/{id}

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app that the string (uuid)


principal belongs to.

path id The ID of the principal. string (uuid)


Example Request

GET https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/principals/c07b7af3-8c9a-4bb1-9a0b-03692ba98d6d

Example Response

{
"id": "c07b7af3-8c9a-4bb1-9a0b-03692ba98d6d",
"type": "User",
"aadTenantId": "0c1cbce0-b823-4acf-be2f-1ac3a4e81c21",
"roles": [
"Owner"
],
"_etag": "c99541ab-a0d2-4807-86f8-e1eb1853eb4f"
}

Remove principal
Removes the principal with the specified ID in the specified app .
Note: Only principals with the Owner role are allowed to remove principals.

DELETE https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/principals/{id}

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app that the string (uuid)


principal belongs to.

path id The ID of the principal. string (uuid)

Example Request

DELETE https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/principals/c07b7af3-8c9a-4bb1-9a0b-03692ba98d6d

Add or update principal


Adds or updates the specified principal that belongs to the specified app . Note: Only principals with the
Owner role are allowed to add or update principals. Note: The aadTenantId field should only be specified in the
request body when the principal being added is of type User .

PATCH https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/principals/{id}

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app that the string (uuid)


principal belongs to.

path id The ID of the principal to string (uuid)


add or update.
TYPE NAME DESC RIP T IO N SC H EM A

body principal The properties that should Principal


be added or updated.

Example Request

PATCH https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/principals/c07b7af3-8c9a-4bb1-9a0b-03692ba98d6d

{
"aadTenantId": "20ba9ed9-d37b-4db0-ade4-f64322ad7c02",
"Type": "User",
"roles": [
"Reader"
]
}

When using Type:"Application" , the aadTenantId must not be used.


Example Response

{
"id": "c07b7af3-8c9a-4bb1-9a0b-03692ba98d6d",
"type": "User",
"aadTenantId": "0c1cbce0-b823-4acf-be2f-1ac3a4e81c21",
"roles": [
"Reader"
],
"_etag": "a98992bf-d7f6-460b-83bb-1498459a6a75"
}

Version
Description
A version represents an .app file that has been uploaded for a specific country in an app .
If a version of an app should be available in multiple countries, then the .app file needs to be uploaded to each
country separately.
Properties
Version

NAME DESC RIP T IO N SC H EM A

appId The ID of the app. string (uuid)

availability The version's availability. enum (Preview, Available, Deprecated)

buildVersion The build number of the version. integer (int32)

countr yCode The country that the version was string


uploaded for.

dependencies The dependencies of the uploaded Dependency[]


package.

majorVersion The major number of the version. integer (int32)


NAME DESC RIP T IO N SC H EM A

minorVersion The minor number of the version. integer (int32)

name The name of the app. string

packageId The ID of the uploaded package. string (uuid)

publisher The publisher of the app. string

revisionVersion The revision number of the version. integer (int32)

status The version's status. enum (Uploading, Uploaded,


UploadFailed)

uploadedOn The UTC date and time the version was string (date-time)
uploaded on.

version The version of the app. string

_etag The entity tag that contains a value string


unique to the entity's current state.

Dependency

NAME DESC RIP T IO N SC H EM A

appId The dependency app ID. string (uuid)

name The dependency app name. string

publisher The dependency app publisher. string

version The minimum version of the string


dependency.

incompatibleFromVersion The initial app version of the string


dependency that is no longer
compatible with the dependent app. If
this value is set then it means that
versions greater or equal to it are
considered incompatible.

List versions
Lists all versions that match the provided filter.

GET https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}/versions?$filter=
<odata_filter>

Parameters

TYPE NAME DESC RIP T IO N SC H EM A


TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app to list the string (uuid)


versions for.

path countryCode The code of the country to string


list the versions for.

query $filter Restricts the set of items OData filter


returned.

Example Request

GET https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/countries/US/versions?$filter=MajorVersion eq 16 and MinorVersion eq 0

Example Response

{
"value": [
{
"version": "16.0.1.2",
"appId": "41a68924-7fcf-4fd0-9200-f10f36a2e213",
"countryCode": "US",
"packageId": "01d39741-8ab1-4fcc-b353-d9208ba475e3",
"publisher": "Example Publisher",
"name": "ExampleApp",
"uploadedOn": "2019-07-09T11:54:45.5414576Z",
"availability": "Available",
"status": "Uploaded",
"dependencies": [
{
"appId": "1914cafc-93b9-46fd-b825-707f1743caee",
"name": "Example Dependency",
"publisher": "Other Publisher",
"version": "1.0.0.0"
}
],
"majorVersion": 16,
"minorVersion": 0,
"buildVersion": 1,
"revisionVersion": 2,
"_etag": "50fec40a-99b6-4743-bbe7-42e95cde2cfa"
}
]
}

Upload version
Uploads an .app file into the specified app and country based on the provided package contents.

POST https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}/versions

IMPORTANT
Make sure that you registered your app with the service and added a country to it, before you attempt to upload the app
version.
NOTE
If you want to update app to a version that introduces breaking changes, see Upgrading an App by Using ForceSync.

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app. string (uuid)

path countryCode The country code. string

body requestData The request data. Upload Version Request

Upload version request

NAME DESC RIP T IO N SC H EM A

initialAvailability The initial availability that the uploaded enum (Preview, Available, Deprecated)
app version should have.

packageContents The base64-encoded contents of the string (byte)


package (.app file) to upload.

Example Request

POST https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/countries/US/versions

{
"initialAvailability": "Preview",
"packageContents": <contents>
}

Example Response
{
"version": "16.0.1.2",
"appId": "41a68924-7fcf-4fd0-9200-f10f36a2e213",
"countryCode": "US",
"packageId": "01d39741-8ab1-4fcc-b353-d9208ba475e3",
"publisher": "Example Publisher",
"name": "ExampleApp",
"uploadedOn": "2019-07-09T11:54:45.5414576Z",
"availability": "Preview",
"status": "Uploaded",
"dependencies": [
{
"appId": "1914cafc-93b9-46fd-b825-707f1743caee",
"name": "Example Dependency",
"publisher": "Other Publisher",
"version": "1.0.0.0"
}
],
"majorVersion": 16,
"minorVersion": 0,
"buildVersion": 1,
"revisionVersion": 2,
"_etag": "50fec40a-99b6-4743-bbe7-42e95cde2cfa"
}

Download version
Downloads the .app file linked to the specified version.

POST
https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}/versions/{versionNumber}
/getPackageContents -OutFile {saveToFile}

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app that the string (uuid)


version belongs to.

path countryCode The country code. string

path versionNumber The version number of the string


version to update.

path saveToFile The path and the name you string


want to use for file you
download.

Example Request
Downloads an app file.

POST https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/countries/US/versions/16.0.1.2/getPackageContents -OutFile "C:\temp\ExampleApp-16.0.1.2.app"

Get version
Gets the version in the specified app and country .
GET
https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}/versions/{versionNumber}

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app. string (uuid)

path countryCode The country code. string

path versionNumber The version number. string

Example Request

GET https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/countries/US/versions/16.0.1.2

Example Response

{
"version": "16.0.1.2",
"appId": "41a68924-7fcf-4fd0-9200-f10f36a2e213",
"countryCode": "US",
"packageId": "01d39741-8ab1-4fcc-b353-d9208ba475e3",
"publisher": "Example Publisher",
"name": "ExampleApp",
"uploadedOn": "2019-07-09T11:54:45.5414576Z",
"availability": "Preview",
"status": "Uploaded",
"dependencies": [
{
"appId": "1914cafc-93b9-46fd-b825-707f1743caee",
"name": "Example Dependency",
"publisher": "Other Publisher",
"version": "1.0.0.0"
}
],
"majorVersion": 16,
"minorVersion": 0,
"buildVersion": 1,
"revisionVersion": 2,
"_etag": "50fec40a-99b6-4743-bbe7-42e95cde2cfa"
}

Update version
Updates the version in the specified app and country with the provided updated data.
Note: only some properties can be updated.

PATCH
https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}/versions/{versionNumber}

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app that the string (uuid)


version belongs to.
TYPE NAME DESC RIP T IO N SC H EM A

path countryCode The country code. string

path versionNumber The version number of the string


version to update.

body version The properties that should Version


be updated.

Example Request
Marking an app version as deprecated.

PATCH https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/countries/US/versions/16.0.1.2

{
"availability": "Deprecated"
}

Example Request
Marks older versions of your app as incompatible with a dependency app, starting with a specific version. In
such cases, make sure you upload another version of your app that is compatible with the new version of the
dependency app.

PATCH https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/countries/US/versions/16.0.1.2

{
"dependencies": [
{
"appId": "63ca2fa4-4f03-4f2b-a480-172fef340d3f",
"incompatibleFromVersion": "16.0.0.0"
}
]
}

Example Response
{
"version": "16.0.1.2",
"appId": "41a68924-7fcf-4fd0-9200-f10f36a2e213",
"countryCode": "US",
"packageId": "01d39741-8ab1-4fcc-b353-d9208ba475e3",
"publisher": "Example Publisher",
"name": "ExampleApp",
"uploadedOn": "2019-07-09T11:54:45.5414576Z",
"availability": "Deprecated",
"status": "Uploaded",
"dependencies": [
{
"appId": "1914cafc-93b9-46fd-b825-707f1743caee",
"name": "Example Dependency",
"publisher": "Other Publisher",
"version": "1.0.0.0"
}
],
"majorVersion": 16,
"minorVersion": 0,
"buildVersion": 1,
"revisionVersion": 2,
"_etag": "3c0f1fd2-266e-491b-82e3-74f09a975267"
}

Environment
Description
Represents a customer's environment that has a specific version of an app installed.
Properties
NAME DESC RIP T IO N SC H EM A

aadTenantId The ID of the customer's Azure Active string (uuid)


Directory tenant.

appId The ID of the installed app. string (uuid)

applicationFamily The environment's application family. string

countr yCode The country code the environment string


belongs to.

locationName The Azure location the environment is string


in.

name The environment's name. string

type The environment's type. enum (Production, Sandbox)

version The version of the installed app. string

List environments
Lists the environment s in the specified app and country that have the app installed.
GET https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}/environments

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app. string (uuid)

path countryCode The country code. string

query $filter Restricts the set of items OData filter


returned.

Example Request

GET https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/countries/US/environments?$filter=version eq '16.0.1.2'

Example Response

{
"value": [
{
"aadTenantId": "539a833c-4e6a-42d8-a081-27fa9d810424",
"version": "16.0.1.2",
"appId": "41a68924-7fcf-4fd0-9200-f10f36a2e213",
"countryCode": "US",
"applicationFamily": "Business Central",
"locationName": "West Europe",
"name": "MyCustomer",
"type": "Production"
}
]
}

Environment Hotfix
Description
An environment hotfix represents the action of pushing out an update (new version ) of an app to a
customer's environment as part of fixing a critical issue.
Only version s where the major and minor components haven't changed can be pushed as hotfixes.
It is also not possible to apply a hotfix to an already installed application version of preview availability. To apply
a hotfix, you need to either uninstall the preview application version from the environment you are trying to
update or change the availability of that application version from preview to available .
Properties
NAME DESC RIP T IO N SC H EM A

appId The ID of the app. string (uuid)

completedOn Date and time (UTC) when the hotfix string (date-time)
was applied.

countr yCode The country code. string


NAME DESC RIP T IO N SC H EM A

createdOn Date and time (UTC) when the hotfix string (date-time)
request was created.

environmentAadTenantId The ID of the customer's Azure Active string (uuid)


Directory tenant.

environmentApplicationFamily The environment's application family. string

environmentName The environment's name. string

errorMessage The error message provided when the string


hotfix was unable to be applied.

id The ID hotfix request. string (uuid)

ignoreUpgradeWindow Determines whether the environment's boolean


upgrade window should be ignored
when applying the hotfix.

runAfter Date and time (UTC) after which hotfix string (date-time)
should start to be applied.

sourceAppVersion The version of the app that was string


installed before the hotfix was applied.

star tedOn Date and time (UTC) when the hotfix string (date-time)
started to be applied.

status Status. enum (Scheduled, Running, Succeeded,


Failed, Canceled, Skipped)

targetAppVersion The version of the app containing the string


fixes that should be applied. The value
is the version that the app will be
updated to.

List environment hotfixes


Lists all the hotfix operations that were requested for a specific app and country .

GET https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}/environmentHotfixes?
$filter=<odata_filter>

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app. string (uuid)

path countryCode The country code. string

query $filter Restricts the set of items OData filter


returned.
Example Request

GET https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/countries/US/environmentHotfixes?$filter=targetAppVersion eq '16.0.1.2'

Example Response

{
"value": [
{
"id": "db311b6a-062e-4756-b17e-73aeb89c45cc",
"environmentAadTenantId": "539a833c-4e6a-42d8-a081-27fa9d810424",
"sourceAppVersion": "16.0.0.5",
"targetAppVersion": "16.0.1.2",
"status": "Scheduled",
"createdOn": "2020-03-05T15:41:20.6468128Z",
"runAfter": "2020-03-05T17:30:00.0000000Z",
"appId": "41a68924-7fcf-4fd0-9200-f10f36a2e213",
"countryCode": "US",
"environmentApplicationFamily": "Business Central",
"environmentName": "MyCustomer",
"environmentType": "Production"
}
]
}

Get environment hotfix


Gets an environment hotfix operation by its ID.
This endpoint can be used to track the status/outcome of a hotfix request.

GET
https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}/environmentHotfixes/{id}

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app. string (uuid)

path countryCode The country code. string

path id The ID of the hotfix request. string (uuid)

Example Request

GET https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/countries/US/environmentHotfixes/db311b6a-062e-4756-b17e-73aeb89c45cc

Example Response
{
"id": "db311b6a-062e-4756-b17e-73aeb89c45cc",
"environmentAadTenantId": "539a833c-4e6a-42d8-a081-27fa9d810424",
"sourceAppVersion": "16.0.0.5",
"targetAppVersion": "16.0.1.2",
"status": "Scheduled",
"createdOn": "2020-03-05T15:41:20.6468128Z",
"runAfter": "2020-03-05T17:30:00.0000000Z",
"appId": "41a68924-7fcf-4fd0-9200-f10f36a2e213",
"countryCode": "US",
"environmentApplicationFamily": "Business Central",
"environmentName": "MyCustomer",
"environmentType": "Production"
}

Schedule environment hotfix


Schedules a hotfix for a specific environment to the specified version .
The hotfix operation ID that is returned can be used to track the status/outcome of the operation (see: Get
environment hotfix).

POST https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}/environmentHotfixes

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app. string (uuid)

path countryCode The country code. string

body environmentHotfix Environment hotfix to Environment Hotfix


schedule.

Example Request

POST https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/countries/US/environmentHotfixes

{
"environmentAadTenantId": "539a833c-4e6a-42d8-a081-27fa9d810424",
"targetAppVersion": "16.0.1.2",
"runAfter": "2020-03-05T17:30:00.0000000Z",
"environmentApplicationFamily": "Business Central",
"environmentName": "MyCustomer",
"environmentType": "Production"
}

Example Response
{
"id": "db311b6a-062e-4756-b17e-73aeb89c45cc",
"environmentAadTenantId": "539a833c-4e6a-42d8-a081-27fa9d810424",
"sourceAppVersion": "16.0.0.5",
"targetAppVersion": "16.0.1.2",
"status": "Scheduled",
"createdOn": "2020-03-05T15:41:20.6468128Z",
"runAfter": "2020-03-05T17:30:00.0000000Z",
"appId": "41a68924-7fcf-4fd0-9200-f10f36a2e213",
"countryCode": "US",
"environmentApplicationFamily": "Business Central",
"environmentName": "MyCustomer",
"environmentType": "Production"
}

Update environment hotfix


Updates an existing environment hotfix operation.
It can currently only be used to cancel a requested hotfix that hasn't yet started running.

PATCH
https://apps.businesscentral.dynamics.com/v1.0/apps/{appId}/countries/{countryCode}/environmentHotfixes/{id}

Parameters

TYPE NAME DESC RIP T IO N SC H EM A

path appId The ID of the app. string (uuid)

path countryCode The country code. string

path id The ID of the hotfix request. string (uuid)

body environmentHotfix Environment hotfix Environment Hotfix


properties to update.

Example Request

PATCH https://apps.businesscentral.dynamics.com/v1.0/apps/41a68924-7fcf-4fd0-9200-
f10f36a2e213/countries/US/environmentHotfixes/db311b6a-062e-4756-b17e-73aeb89c45cc

{
"status": "Canceled"
}

Example Response
{
"id": "db311b6a-062e-4756-b17e-73aeb89c45cc",
"environmentAadTenantId": "539a833c-4e6a-42d8-a081-27fa9d810424",
"sourceAppVersion": "16.0.0.5",
"targetAppVersion": "16.0.1.2",
"status": "Canceled",
"createdOn": "2020-03-05T15:41:20.6468128Z",
"runAfter": "2020-03-05T17:30:00.0000000Z",
"appId": "41a68924-7fcf-4fd0-9200-f10f36a2e213",
"countryCode": "US",
"environmentApplicationFamily": "Business Central",
"environmentName": "MyCustomer",
"environmentType": "Production"
}

Getting detailed error messages


To get detailed error messages from t API calls, wrap the calls in a try-catch block, as shown in the following
PowerShell example:

try {
Invoke-WebRequest ....
}
catch [System.Net.WebException]
{
$Exception = $_.Exception
$respStream = $Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($respStream)
$respBody = $reader.ReadToEnd() | ConvertFrom-Json | ConvertTo-Json -Depth 100
$reader.Close();
Write-Error $Exception.Response.Headers["ms-correlation-x"]
Write-Error $Exception.Message
Write-Error $respBody -ErrorAction Stop
}

Please make sure you provide full output in textual format when reporting the issues to Microsoft.

See Also
App Management for ISVs
Upgrading an App by Using ForceSync
2/6/2023 • 2 minutes to read • Edit Online

This article provides guidelines for using ForceSync option to upgrade an app to a version that introduces
breaking changes.

Overview
When you upgrade an app to a new version, the database is synchronized with any schema changes introduced
by the new app version. Under normal operation, if the app introduces any breaking changes, like removing a
field or changing its data type, the synchronization will fail, preventing the upgrade. However, the service
includes a property called syncMode that you can set to "ForceSync" , which will apply the breaking changes. If
you're familiar with Business Central on-premises, this operation is similar to using the Sync-NAVApp cmdlet
with -mode ForceSync parameter.
This property only works with side-by-side upgrades using Microsoft Lifecycle Services (LCS). You can't use it for
breaking changes in a hotfix pushed from App Management API. So make sure you plan your changes when
preparing new minor or major upgrades.

IMPORTANT
Use this option with caution. When you use the syncMode = "ForceSync" , it applies breaking changes forcefully,
typically deleting the data in the objects that have new schema. It can also break other apps that run on top of your
objects. Before using this option in production, test it on both on-premises and online (using Sandboxes). It's also
recommended that you export a BACPAC of your production environment from the Business Central admin center before
the upgrade.

Upgrade an app version using ForceSync


1. Using the App Management API, upload a new app version as usual.
For more information, see App Management API - Upload Version.
2. In Microsoft Lifecycle Services, create a new deployment that will use new app version.
3. Using Windows PowerShell, issue PATCH request, like the following example, to change the syncMode
property on the app version:

$version = 'target_version'
$url =
https://apps.businesscentral.dynamics.com/v1.3/apps/$appID/countries/$country/versions/$version
$body = @{
syncMode = "ForceSync"
}

Invoke-WebRequest -Uri $url -Headers $headers -Body (ConvertTo-Json $body) -Method Patch

Replace target_version with the new version of your app, for example, 18.0.23456.21212.
4. In LCS, upgrade an environment from the old version to the new version. The new app version will be
upgraded using ForceSync.
You can always switch to the normal sync mode for an app issuing another PATCH request that sets the
syncMode to "Sync" :

{
"syncMode": "Sync"
}

See Also
App Management API
Manage Apps in the Business Central Administration Center
Get Started as a Reseller of Business Central Online
2/6/2023 • 12 minutes to read • Edit Online

If you want to build your business on Dynamics 365 Business Central online, you must get set up as a reseller in
the Microsoft Partner Center. In this article, we take you through the first steps in your journey.

Step 1: Become a partner


Becoming a Microsoft partner gives you access to the Microsoft resources needed to sell solutions. The steps in
this section below are required to gain access to the programs that enable are intended to help you get set up to
sell Business Central.
In order to be able to service Business Central licenses and provide help and support to your customers, your
company must have a Microsoft Partner ID (MPN ID), and you must enroll in the Cloud Solution Provider (CSP)
program.
Join the Microsoft Partner Network
Microsoft Partner Network (MPN) membership unlocks our best resources to differentiate your business, take
your product to market, and sell your solutions. To become a partner, you must join the Microsoft Partner
Network (MPN), at which time you will be assigned an MPN ID. MPN membership is free to all partners; you can
enroll in the MPN here.
Once signed up, you will get an MPN ID – your gateway to access all the membership resources and benefits for
your partnership with Microsoft. There is no cost to obtain a MPN ID as a Network member, and with options to
upgrade to an Action Pack subscription or work toward a competency, you can access even more benefits.
Set up your Partner Center account
Once you have joined the Microsoft Partner Network (MPN), you can set up your Partner Center (PC) account.
The Microsoft Partner Center is a generic portal where partners can sell and manage customer subscriptions for
Microsoft services, such as Microsoft 365, Azure, Dynamics 365, and others, as well as for some third-party
products. For more information, see the Partner Center documentation.
Your Partner Center account provides you with access to pricing information, tools and services, and enables
you to manage admin credentials for your company's work account. Partner Center is also where you can
purchase or renew subscriptions to Microsoft Action Packs, create a business profile to receive and manage
sales leads from Microsoft, and see if you qualify for co-selling opportunities.
Enroll in the CSP program
The Cloud Solution Provider (CSP) program helps your company to be more involved in your customers'
businesses, beyond reselling licenses. In CSP, you can choose to enroll as an indirect reseller or a direct bill
partner.
In most cases, you will enroll as an indirect reseller and then work with an indirect provider, also referred to as a
distributor, who then manages all interaction with Microsoft in terms of licensing and technology, so that you
can focus on sales and support. If you decide to enroll as a direct bill partner in order to fully own the end-to-
end relationship with both customers and Microsoft, make sure that you meet the eligibility requirements. For
more information, see Enroll in the Cloud Solution Provider program in the Microsoft Partner Center content.
The Microsoft Partner Center is a generic portal where partners can sell and manage customer subscriptions for
Microsoft services, such as Microsoft 365, Azure, Dynamics 365, and others, as well as for some third-party
products. For more information, see the Partner Center documentation.
Some indirect providers (distributors) provide their resellers with a custom portal that optimizes and enhances
the experience beyond the Partner Center. They can also provide indirect resellers with an API to automate some
of the customer onboarding steps. Contact your indirect provider to find out more.
Both indirect resellers and direct bill partners can access and support their customers' Business Central by
setting up a reseller relationship with them.
To service customers in a specific country, your partner company's Azure Active Directory (Azure AD) tenant and
CSP account must be registered in the regional CSP market that covers that country. For more information, see
Cloud Solution Provider program regional markets and currencies.

NOTE
When you buy Business Central offers on behalf of your CSP customers, the CSP offer must be available in both your own
tenant's country and in your customer's tenant's country. For example, if your tenant is located in Slovakia and the
customer's tenant is in Germany, you will not be able to sell Dynamics 365 Business Central Premium to that customer,
because this offer is currently not available in Slovakia.
Similarly, if your tenant is located in Germany and the customer's tenant is in Slovakia, you will not be able to sell
Dynamics 365 Business Central Premium to that customer, because this offer is currently not available in Slovakia.

In the Microsoft Partner Center documentation, you can learn how to request a reseller relationship with
customers, assign licenses to users, and create new subscriptions. Business Central is one of the subscriptions
that you can create, and there are Business Central-specific license types that you can assign to users.
You must also assign certain roles to users in your own organization so that they can support your customers.
Add users from your own organization
In most cases, your partner company includes employees with different responsibilities, and you can assign
different roles depending on people's responsibility. This way, you can be very explicit about who from your staff
can access your customers' data, for example.
For each user, you can assign permissions for 2 categories of tasks:
Managing your organization's account
This controls access to the functionality of the Partner Center portal
Assisting your customers
This controls access to your customers' environments
When you establish a reseller relationship with a customer in Partner Center, you must specify which people
from your organization will assist that customer's tenant as either Admin agent or Helpdesk agent. These users
can manage implementation, support, and troubleshooting tasks for your customers. Once the reseller
relationship with a customer is established, they will be able to login into the Business Central environments of
the customer without a license. The number of partner users that can access customer environments is not
restricted.
This way of accessing customer resources is called delegated administration, and the partner users are therefore
called delegated administrators or delegated admins in daily shorthand. For more information, see Delegated
Administrator Access to Business Central Online.
Since February 2022, you can set up security groups with granular delegated admin privileges to better control
who has access to which customers with which level of access to the customer's Business Central environment.
This way, the delegated admins no longer have to be global admins for the customer's Active Directory. For
more information, see the Delegated Administrator Access to Business Central Online section, and also the
Admin roles article in the Microsoft 365 admin content.
NOTE
These users cannot provide accounting services for the customers. For this purpose, the customers must use the
External Accountant license, which is also available via CSP.

Cau t i on

Quite often, partner users are registered as business-to-business (B2B) guest users in their customer's Azure
Active Directory (Azure AD), such as to collaborate through Teams. However, when a partner user is added as a
guest to their customer's Azure AD, they can no longer log in as a delegated admin into the customer's Business
Central. These guest users do not have a valid Business Central license assigned to them. But if the partner user
has granular delegated admin privileges, they can access the customer's Business Central administration center
and manage the environments there. Starting in 2022 release wave 2, partner users that are guest users and
have granular delegated admin privileges are no longer blocked from accessing Business Central. But we
continue to consider it a best practice that customers do not invite partner users to their tenant as guests but
ask them to set up granular delegated admin privileges, using the Dynamics 365 administrator role. For more
information, see Move to GDAP and remove DAP in the Partner Center FAQ.
For more information, see Delegated Administrator Access to Business Central Online.

Step 2: Go to market
When you become a Microsoft Partner Network member, you gain access to membership benefits that can help
you build and grow your business. For more information, see Explore your Go-To-Market with Microsoft offers
in the Partner Center docs.
As a Dynamics 365 reseller, you benefit from Microsoft's investments in an always up-to-date modern platform,
you can bundle recognized apps from the Microsoft commercial marketplace into an offering that fits the needs
of your customers, reach more customers by using Microsoft's commercial marketplace to promote your
packaged consulting service offerings or customization services, and streamline your own processes and build
tools with Power BI, Power Automate, and Power Apps connected to Business Central.
The Dynamics 365 Business Central Partner Portal landing site has plenty of material to help you build a
practice, go to market, drive readiness, and keep track of upcoming events (requires a partner account).
Marketing assets
Microsoft provides marketing assets that you can use to build a business based on Microsoft. For more
information, see the following sites:
Partner Network resources
Brand and trademark basics for partners
Go-to-market with Microsoft
Specifically for going to market with Business Central, Microsoft provides resources and guidance on the
Business Applications for small and medium-sized businesses (SMBs) site. For more information, see Business
Central Go-To-Market resources.

Step 3: Give powerful demos


You can create a trial environment based on content in cdx.transform.microsoft.com.
For more information, see Preparing Demonstration Environments of Dynamics 365 Business Central.

Step 4: Help your customers get started


When you onboard customers to Business Central, you have access to their account as a delegated
administrator and can help them get things set up. For more information, see Administration of Business Central
Online.
Connect with customers
As a CSP partner, you can manage a customer's subscriptions and services on their behalf in the Partner Center
by establishing a reseller relationship with your customers. If they already have an account, such as if they
currently use Microsoft 365, other Dynamics 365 apps, or PowerApps, for example, you can send them an
invitation straight from the Partner Center. For more information, see Connect with customers in Partner Center
(indirect providers/distributors) and Connect with customers (indirect resellers).
When the customer's internal administrator receives the invitation link and navigates to it, they must
acknowledge that they have read the Microsoft Customer Agreement and that they can authorize you as their
reseller on behalf of their organization. For more information, see Confirm customer acceptance of the
Microsoft Customer Agreement.
When a customer accept this reseller relationship, delegated administration privileges must be set up . For more
information, see Delegated Administrator Access to Business Central Online.
If you are working as an indirect reseller, your indirect provider (distributor) must associate your customers with
you in their Partner Center.
The customer can decide to remove their partner's delegated admin privileges from their tenant, but still retain
the relationship with their partner for subscription and license renewal purposes. Removing delegated admin
privileges will block the partner's access to the customer's Business Central. The access can be restored if the
partner sends the reseller relationship request to the customer again.
If the customer wants to cancel their relationship with their partner, the partner must remove the relationship in
Partner Center.
Get Business Central right for the customer
The default version of Business Central is just that - a default version. In many cases, you'll enhance the default
version with apps from the Microsoft commercial marketplace. But you can also customize pages for a profile
and change which UI elements are visible. For more information, see Customize Business Central in the business
functionality content.
If your customer wants more tweaks, you can create customizations of profiles and pages in code. For more
information, see Customizing the User Interface for User Roles in the developer content.
You can also use configuration packages to quickly apply the same settings as usual to new environments.
Move the customer from a trial to a paid subscription
If your customer decides to start using Business Central to run their business, they must switch to a paid
subscription. Both the internal admin and the delegated admin can assign licenses to users in the Microsoft 365
admin center. For more information, see Buy or remove licenses in the Microsoft 365 content.

IMPORTANT
Specifically for businesses who want to convert a 30-day trial company into their actual production company, the first
user who signs into Business Central after the license was applied to their tenant must be a user with this license
assigned. This way, the 30-day trial ends, and any trial-related notifications disappear so that users can use Business
Central to do work.
If an administrator is the first person to sign in after the license was applied to the tenant and to users, then the trial will
continue until it expires.

If the customer has tried out Business Central using a pre-configured demonstration company that you have
prepared in other ways, they can now sign up for Business Central using their own work or school account so
that you can assign the Business Central license to their Microsoft 365 tenant.
You can help them migrate their data from their legacy system. For more information, see Migrate On-Premises
Data to Business Central Online.

Step 5: Configure the support experience


As a Business Central reselling partner, you are an administrator of your customers' Business Central tenants,
and you are the first line of support. This means that you will get requests for support from your customers that
you must triage, investigate, and either resolve or escalate to Microsoft.
Your company must be registered as a Microsoft partner, and it must have the Advanced Support for Partners
(ASfP) or Premier support plan. Your service account manager can get you more information about getting the
ASfP. If you already have a support plan, the Technical Benefits tab in the Partner Center lists the contract ID and
access ID that you must specify when you submit a new support request on behalf of your customer. If you're
not sure how to find the information, the service account manager can get the information for you.
For more information, see Technical Support for Business Central and Managing Technical Support.

Step 6: Maintain your customers' Business Central


As a Business Central reselling partner, you are the administrator of the Business Central tenants of your
customers. You are expected to help your customers maintain their solution, including setting the upgrade
window, monitoring telemetry, updating customizations, and managing apps.
For more information, see Administration of Business Central Online and The Business Central Administration
Center.

See also
Administration of Business Central Online
Deployment of Dynamics 365 Business Central on-premises
Trials and Sign-ups for Business Central Online
Licensing in Dynamics 365 Business Central
Learn how to partner with indirect providers in the Cloud Solution Provider program
Dynamics 365 Business Central Partner Portal
Set Up Company Configuration Packages
2/6/2023 • 10 minutes to read • Edit Online

As you grow your business as a reseller of Business Central, you will likely come to rely on a set of company
types that you use with most of your Business Central prospects. You can streamline your implementation
process by turning these types into configuration packages that are available for reuse.
After you have set up a company in Business Central that suits your needs, you can create a configuration
package that contains relevant setup data from this company. You can then use it when you create a new
company that is to be configured in the same way.
To facilitate the import of master data, such as customer and vendor information, you can use configuration
templates. Configuration templates contain a set of default settings that are automatically assigned to the
records imported into Business Central. Configuration templates are an alternative to the cloud migration tools
that you can use to migrate customer data from supported products. For more information, see Migrate On-
Premises Data to Business Central Online.

TIP
Use these capabilities to scale your business as a reseller. Most of the relevant pages apply to both Business Central online
and on-premises. However, some processes rely on access to the underlying database and are too complex to use for
Business Central online. For Business Central on-premises, you probably want to use Windows PowerShell to help you
deploy. For more information, see Administration of Business Central On-Premises and Administration of Business Central
Online, respectively.

Configuration packages
By default, Business Central online comes with one configuration package for Microsoft's default application,
including local functionality. You can copy that and make relevant changes in the copy.
Many of our reselling partners create a configuration package for each functional area. For example, create a
package for the manufacturing functionality and another for sales. That lets you apply and set up new areas in a
company as you need them.
We recommend that you create configuration packages with most of the setup tables already filled in, so that
only a few settings must be tweaked for each customer. For example, when you create a new company, the No.
Series and the No. Series Line tables are filled in with a set of number series and starting numbers. The
corresponding No. Series fields in the setup tables are also filled in automatically. You do not have to do the
work of entering number series and other basic setup data. You can also manually change all default data that is
used with RapidStart Services by using the configuration worksheet.
Another approach would be to create a package that includes the tables that define setup, such as the following:
General Ledger Setup
General Posting Setup
VAT Posting Setup
Inventory Posting Setup
Purchases and Payables Setup
Sales and Receivables Setup
Warehouse Setup
Inventory Setup
Manufacturing Setup
Fixed Asset Setup
Marketing Setup
Service Setup
To see a complete list of setup tables in Business Central, choose the icon, enter Manual Setup , and then
choose the related link.

TIP
Optionally, use the configuration worksheet to gather together and categorize the information that you want to use to
configure a new company, and arrange tables in a logical way. Formatting in the worksheet is based on a simple hierarchy:
areas contain groups, which in turn contain tables. Areas and groups are optional but useful. You can then add the
worksheet lines to a new configuration package.

Before you create a configuration package


There are some things to consider before you create a configuration package because they will impact you or
your customer's ability to import it.
Tables that contain posted entries
You cannot import data to tables that contain posted entries, such as the tables for customer, vendor, and item
ledger entries, so you should not include this data in your configuration package. You can add entries to these
tables after you import the configuration package by using journals to post the entries. For more information,
see Posting Documents and Journals in the business functionality content.
Table names that contain special characters
Use caution if you have tables or fields that have the same temporal name but are differentiated by special
characters, such as %, &, <, >, and ,. For example, a table might contain the Field 1 and Field 1% fields.
The XML processor that generates the .rapidstart files accepts only some special characters, and will remove
those it does not. If removing a special character, such as the % sign in "Field 1%," results in two or more tables
or fields with the same name an error will occur when you export or import a configuration package.
Permissions
The process of creating and importing a configuration package involves the following effective permissions for
all tables in the package:
The user who exports data for the configuration package must have Read effective permissions.
The user who imports the configuration package must have Inser t and Modify effective permissions.
Database schema
When exporting and importing configuration packages between two company databases, the databases must
have the same schema to ensure that all data is transferred successfully. This means that the databases should
have the same table and field structure, in which the tables have the same primary keys and fields have the
same IDs and data types. In practical terms, that means that your configuration package must be based on the
same version of Business Central as the customer environments that you intend to apply it to.
You can import a configuration package that has been exported from a database that has a different schema
than that target database. However, any tables or fields in the configuration package that are missing in the
target database will not be imported. Tables with different primary keys and fields with different data types will
also not successfully import. For example, if the configuration pack includes table 50000, Customer that has
primary key Code20 and the database to which you import the pack includes table 50000, Customer Bank
Account that has the primary key Code20 + Code 20 , then data will not be imported.

To create a custom company configuration package


1. Create a new company. For more information, see Create New Companies in Business Central in the
business functionality content.
2. Set up the new company in the way you need. Fill in all required setup tables.
Optionally, use the default configuration package in the Cronus demonstration company to set up the
base application. Then, add your own best practices on top.
Next, you'll add this setup to a configuration package. You can set up the tables that you want to add to
the package in the Configuration Worksheet page and then add a configuration package to the lines in
that worksheet. Or you can add the tables directly to the package in the Configuration Package page.
In the following steps, we assume that you prefer to set things up in the worksheet, but you don't have to.
3. Open the Configuration Worksheet page.
4. Add a new line of the type Area , and then add groups and the tables that you want to transfer to another
company to the package. Hover over a field to read a short description.

TIP
Take a look at the default configuration package for the demonstration company for inspiration for how to set up
the configuration.

a. Choose the Get Tables action. On the Get Config. Tables request page, specify the types of
tables that you want to add to the configuration, and set the relevant filters. Then choose the OK
button.
To exclude the configuration questionnaires, configuration templates, and configuration worksheet
tables from the package, select the Exclude Configuration Tables check box on the Config
Package Card page. Otherwise, these tables will be added to the list of package tables
automatically when you export the package.
b. To add related tables, choose the Get Related Tables action.

NOTE
Related tables will not be added with the Get Related Tables action if either of the following is true:
The relation is conditional.
Example: If you get related tables for the Customer table, then the Location table will not be added,
since it is only conditionally related to the Customer table, namely if the Location Code field in the
Customer table is filled in.
The related table is filtered.
Example: A field in the related table has a WHERE clause. The reason for this is that the involved
relations information is stored in the Field system table, which is not fully accessible to the application.
You must add such types of tables manually.

For each table, you can specify which fields to exclude, and you can modify the default processing
order for each field. Business Central checks if there are related fields that you must configure in
the Config. Package Fields page.
c. Optionally, for each table, modify which fields must be included in the package.
Select a table for which you want to specify field information, and on the Actions tab, in the Show
group, choose Fields .
To select just the fields you want to include, choose the Clear Included action. To add all fields,
choose the Set Included action.
To specify that the field data should not be validated, clear the Validate Field check box for the
field.
5. Assign the worksheet lines to an existing package.
a. Select the relevant lines, choose the Assign Package action, and then, in the Configuration
Packages page, choose the relevant package, or create a new one.
If a table is not already included in the package, it will now be added. The package code field on the
worksheet line will be filled in with the code of the package that the table is assigned to.
If you choose an existing package, you can see how many tables are already in the package by
reviewing the information in the No. of Tables field.
6. Optionally, create a questionnaire for the most frequently used setup tables so that you can get specific
information from your prospects and customers that will help you set up their Business Central.
a. On the Configuration Questionnaire page, add a new questionnaire, and then choose the
Questions Areas action.
b. In the Config. Question Area page, in the Table ID field, choose the ID of the table for which
you want to collect information. The Table Name field is automatically filled in.
c. Choose the Update Questions action. Each field in the table is added to the questionnaire with a
question mark following its caption in the Question field.
You can rephrase the question to make it clear that it is a question that should be answered. For
example, if a field is called Name , you could edit the related question to state What is the name of
the account. You can also provide guidance in the Reference field, including a URL to a page that
provides additional information for example.
You can also delete any questions that you do not want to include in the questionnaire.

NOTE
The Answer Option field describes the format that the answer to the question must meet, such as Code
or Text.
As needed, you can also define default answers in the Answer field. These values are used by default for
custom setup. However, the person filling in the questionnaire can modify and update the answer.

d. Repeat steps 2 and 3 for any additional areas that you want to add to the questionnaire, and then
return to the Configuration Questionnaire page.
Optionally, export the questionnaire to Excel. Then, you can use the Excel workbook to get answers
from your prospects and customers. There are worksheets for each of the question areas that have
been created for the questionnaire.

NOTE
You may encounter the following error when you run an English version of Excel, but have your regional
settings configured for a non-English language: Old format or invalid type library. To fix this error, make
sure that the language pack for the non-English language is installed.
7. Optionally, create configuration templates to make it easier to import master data, such as customers,
vendors, contacts, or items.
Use the built-in configuration templates, or create your own templates in the Configuration Templates
page. This is mainly useful if you're going to migrate customer data to Business Central on-premises and
then switch to the cloud. For more information, see Apply Company Configuration Packages.
You can export the templates as Excel workbooks so that you can work with customer data in Excel.
8. Export your package as a .rapidstart file, or export it to Excel.
The next time you're going to set up Business Central for a new customer, you can apply your configuration
packages and get started fast. For more information, see Apply Company Configuration Packages.

See Also
Apply Company Configuration Packages
Migrate On-Premises Data to Business Central Online
FAQ about Migrating to Business Central Online from On-Premises Solutions
Administration of Business Central Online
Administration of Business Central On-Premises
Get Started as a Reseller of Business Central Online
Onboarding experiences in Business Central
Onboarding experiences in Business Central
2/6/2023 • 2 minutes to read • Edit Online

Setting up Business Central for a customer usually involves manual setup from the partners' side. Often this
setup time is spent on basic settings that do not provide additional value to the specific customer but are more
generic and address the customer's industry or type of business. This is costly for the customer and can be a
bottleneck for you as a partner.
Microsoft provides tools you can use to help speed up this process and enable the customer to more easily learn
how to use the product and get to productive usage faster. This will save costs on the customer side and free up
your consultants' time.
The onboarding framework in Business Central presents all users with a consistent onboarding experience when
it comes to an introduction to the product itself. Partners can still use any other methodology that they prefer,
but the tools in the onboarding framework provides a native experience.

Onboarding elements at your disposal


In the following sections you find descriptions of components you can use when authoring onboarding
experiences for your customers along with guidance to where and how to use them.
Banner
For more information, see Onboard New Users with the Welcome Banner.
The checklist
For more information, see Get Users Started with the Checklist.
Teaching tips and tours
For information, see Teaching tips and in-app tours for onboarding users.

See also
Get Users Started with the Checklist
Onboard New Users with the Welcome Banner
Teaching tips and in-app tours for onboarding users
User Assistance Model
Extend and Collaborate on the Help
Migrate On-Premises Data to Business Central Online
FAQ for Developing in AL
2/6/2023 • 2 minutes to read • Edit Online

This topic contains a number of frequently asked questions and answers to these questions.

How do I get started?


For an overview of developing apps for Dynamics 365 Business Central, see aka.ms/GetStartedWithApps
Next, follow the Get Started with AL to set up the tools.

Which version of the AL Language extension should I use?


For Dynamics 365 Business Central cloud sandboxes you must use the AL Language extension available in the
Visual Studio Code Marketplace.
For the latest Developer Preview releases you must use the AL Language extension that is available in the next
major artifact through the "Ready! for Dynamics 365 Business Central" program on Microsoft Collaborate.

How do I enable the debugger?


To read about enabling debugging in AL, see here Debugging. To read about snapshot debugging, see Snapshot
Debugging.

Where do I find help regarding AppSource validation and submission?


When submitting an app for AppSource, you must make sure that it validates against the Technical Validation
Checklist. For frequently asked questions, see Technical Validation Checklist FAQ.

What constitutes the identity of an app?


To read about app identity and why it is important to keep certain settings for an app unchanged, see App
Identity.

File APIs are not available in Extensions V2. What do I do?


Code that relies on temporary files must be rewritten to rely on InStream and OutStream types. Code that relies
on permanent files must be rewritten to use another form of permanent storage.

DotNet types are not available in Extensions V2. What now?


For cloud solutions .NET interop is not available due to safety issues in running arbitrary .NET code on cloud
servers.
With the AL Language extension, you can find AL types that replace the most typical usages of .NET like HTTP,
JSON, XML, StringBuilder, Dictionaries, and Lists. Many .NET usages can be replaced directly by the AL types
resulting in much cleaner code. For more information, see HTTP, JSON, TextBuilder, and XML API Overview.
For things that are not possible to achieve in AL code, the recommendation is to use Azure Functions to host the
DLL or C# code previously embedded and call that service from AL.
Extensions published from Visual Studio Code or created using
Designer have disappeared from a sandbox environment. Why?
Extensions that have been published to a sandbox environment from Visual Studio Code or created using
Designer are removed when the sandbox environment is updated or relocated within our service. However, the
data of an app is not removed, so you only have to re-publish and install the app to make it available.
If you have per-tenant extensions (PTEs) installed that depend on extensions published from Visual Studio Code,
the per-tenant extensions will be removed too.
For more information, see Sandbox Environments.

Can I create something similar to Menusuites?


In the AL Language extension, the concept of Menusuites is not supported. The two primary purposes of
Menusuites are:
Making pages searchable
Making pages accessible through a navigation structure
The first purpose can be achieved in Extensions by using the new properties added to Pages and Reports. For
more information, see Adding Pages and Reports to Search.
The second purpose can be achieved by extending the Navigation Pane page and/or by adding Actions to other
existing pages that can serve as a navigation starting point. For more information, see Adding Menus to the
Navigation Pane.

How do I upgrade Extensions V1 to Extensions V2?


For information on upgrading, see the following topics: Upgrading Extensions v2 and Converting from
Extensions v1 to Extensions v2.

See Also
Get Started with AL
Keyboard Shortcuts
AL Development Environment
FAQ about Library and Dependency Apps in
Business Central
2/6/2023 • 2 minutes to read • Edit Online

This section contains answers to frequently asked questions about library apps and dependency apps in
Business Central.

What is a library app?


A library app contains common code that other apps depend on. If you're going to have multiple AppSource
apps that all share common code, such as licensing, registration, and so on, you can put that common code into
a library app and have the AppSource apps depend on the library app.

How does the library app get installed to a tenant?


A library app doesn't appear on AppSource. It only lives in Business Central. Our service is built to install the
library apps behind the scenes. Here's how it works. Customers find an app they want to install on AppSource.
That customer doesn't know the app even has library app(s). When they select to install the app, our service
looks into that apps json/manifest to see if it first needs to install any library/dependency apps it may depend
on. If so, it installs them first before installing the main AppSource app.

What is a dependency app?


A dependency app isn’t much different from a library app. A dependency app does have its own offer on
AppSource. For example, you might have AppSource “App A” that serves a purpose on its own and is listed on
AppSource. You then also have “App B” as its own offer on AppSource but it does depend on code within “App A”
and needs “App A” to be installed before it can be installed. This is really the only difference though. Behind the
scenes, library and dependency apps behave the same when it comes to walking that dependency chain and
auto installing any app the top-level app depends on.

Can I have multiple library apps for my AppSource app?


Yes. Just make sure you list all library apps as dependencies within the AppSource app json file/manifest.

When I get the latest updated version of my app, why don't I get the
updated library/dependency apps that my AppSource app depends
on?
Libraries are updated only when the new version of your app requires a higher version than the version
currently installed in your environment. If you want your library app to be automatically updated when your
AppSource app is updated, you must increase the minimum version required in the manifest (app.json) of your
AppSource app.
You can also uninstall and reinstall the library/dependency app to have it updated.

What are the validation requirements for library apps


Library apps only get validated technically, but don't go through any type of marketing validation. The technical
requirements are described here.
See also
FAQ about Managing and Submitting your Business Central Offer
FAQ about Updating your Business Central App
Update Lifecycle for AppSource Apps FAQ
The Lifecycle of Apps and Extensions for Business Central
FAQ about Testing your Business Central App
2/6/2023 • 4 minutes to read • Edit Online

This section contains answers to frequently asked questions about testing your app when you submit an app for
Business Central.

Since my app goes through validation, do I really need to thoroughly


test my app?
Yes. It's your app and you're the expert, so you should have a vested interest in high quality. The main goal of
validation is to ensure app code is meeting requirements and policy. The testing done during validation is only
to ensure good user experience on the most common app scenarios. We don't test every scenario of an app.
Using customers to find bugs isn't the proper approach.

Is it ok to submit my app for validation before we complete our own


testing?
No. Please, don't submit your app for validation until it has been 100% tested. This will lead to many delays in
the validation process otherwise. Also, it wastes time and resources.

Is it ok to test my AppSource app in an on-premises environment?


No. You must test your app using Business Central online. Although Business Central online and on-premises
are similar, they aren't the exact same. If you only test on-premises, invariably issues will be found in our
validation testing.

Does it really matter what version of Business Central I test on before


submitting my app for validation?
Yes. It's critical that you always test on the latest version at the time when you're ready to submit for validation.
Testing on the wrong version usually leads to validation failure. For example, let’s say the latest version of
Business Central is 15.4 at the time when you submit for validation you tested on 15.0. The product has changed
between those versions, and deprecated features or other changes could result in your app behavior changing.
We recommend that you consider using Docker containers. Use the Get-BcArtifactUrl function in the
BCContainerHelper PowerShell module to give you the artifact URL for the latest sandbox build for the specified
country. You don’t have to figure out what product version is active at time of submission. That function does it
for you.

How thorough should our testing be?


You should always test with 100% coverage, or at least as close to 100% as you can get. The testing should be a
combination of automated and manual tests. The apps with good testing infrastructure behind them are the
most successful.

Do I have to test on every country that I intend to support with my


app?
Yes. If you support multiple countries, test your app on every country. Each country's code base is slightly
different from both the base application and other countries. It's critical to make sure that the app publishes,
syncs, and installs on every country you support. Because an app installs fine on one country doesn’t mean it
will publish/install fine on another. We have seen many times where it passes on one but fails on another during
our validation.

Do you have recommendations on maintenance testing of our apps?


Yes. You should be testing your apps against our various build branches. Through Docker, you have access to our
latest public sandbox builds and through the "Ready! for Dynamics 365 Business Central" program on Microsoft
Collaborate you can also get access to Next Minor and Next Major builds. Test often, especially against the Next
Minor build. This allows you to catch any bugs that may arise from core changes in the product.

I only made minor code changes in my updated app. Can I test just
these changes?
No. You should always test 100% coverage no matter what. Testing only what you changed isn't the correct
approach. Even minor changes can lead to breaking changes where you least expect it.

Do I need to do upgrade testing?


Yes, this is a must. If an app fails to upgrade, customers are unable to get your updated app. This is one of the
common failures we see today in validations. You should want your app upgrade to work optimally.

Any recommendations on upgrade testing?


Test the upgrade with extensive app data included. Many of the upgrade failures for customers are data related.
The upgrade fails because specific data scenarios weren't considered for testing. Or worse, the upgrade
succeeds, and data is lost.

Do I only need to do upgrade testing from previous version to


current?
No. It's important you test from various previous versions of your app. This is because we don't automatically
upgrade apps for minor releases. You could have a tenant back on version 1.0.0.0 of your app and have to jump
all the way to version 1.0.0.5. We don’t guarantee direct upgrades of apps from their most previous version.

See also
FAQ about Updating your Business Central App
FAQ about Library & Dependency Apps in Business Central
Update Lifecycle for AppSource Apps FAQ
The Lifecycle of Apps and Extensions for Business Central
FAQ about Updating your Business Central App
2/6/2023 • 5 minutes to read • Edit Online

This section contains answers to frequently asked questions about updating your app for Business Central.

Is it the same process for an app update as the first version?


Yes. You upload the updated app file into Partner Center and submit as normal. It goes through a more scaled-
back validation process than your original version, but it does get validated. If it fails validation, it comes back to
you for fixing. If it passes validation, it gets checked into Business Central.

What are some "need to know" considerations with an updated app?


When you submit an updated version of your app, you must increase the version number in the app's
json/manifest files. Business Central doesn’t allow overwrites. So we need the version number increased for us
to check the updated app into our service upon it passing validation.
Never change the app's App ID in the json/manifest files. This is must stay the same across versions for various
reasons, not least for upgrade reasons.
For information about what constitutes the identity of an app, see App Identity.

When is my updated app available for tenants to install?


As soon as your updated app passes validation and is checked into our service, it then becomes the active
version (for whatever the current Business Central version is at that time). Even though your offer might still
show as in progress in Partner Center, the updated app is active and ready to install. Also, even though your
version number in AppSource might show as older, tenants will still get this latest updated version. For example,
your updated version might be version 1.0.0.5. And in AppSource it might still show 1.0.0.1. Tenants will get the
version 1.0.0.5.

What version of Business Central is my updated app compatible with?


When you submit your app for validation, we validate it against the latest version at that point in time. Once the
app passes validation, it is then checked into our service and configured for that version of Business Central,
unless a newer version has been released in the meanwhile. For example, if you submit your app and the latest
version of Business Central at that time is 16.1, your app will then be compatible and configured for 16.1. When
versions 16.2, 16.3, and so on roll out, your app is automatically configured for the latest version. Tenants that
are on earlier versions of Business Central will not get that updated version. They still however can install the
previous versions of your app. They will get the version of your app that is configured for the version of
Business Central that their tenant is on.

When tenants have their Business Central version upgraded, do apps


ever get automatically updated?
For minor releases, we do not auto-update apps. This is because of customer feedback and them not wanting
their apps auto updated. The only exception to this is if an app will be broken in a minor release due to changes
in the base product. In this case, we configure that app in our service as required. When tenants then get
upgraded to that minor release, if they have that app, it then gets updated automatically. This is to avoid the app
being broken for the customer.
For major releases, we do auto-update every app on every tenant to the app’s latest available version. We
consider major releases to be our "refresh" releases.

How do tenants that already have an existing version of my app get


my latest updated version?
By uninstalling and reinstalling the app. When doing the reinstall, it calls into our service and finds the latest
active version of an app. There is a new Manage Apps page in the Business Central administration center that
will soon allow updating of AppSource apps without having to do uninstall and reinstall.

Do I have to submit an updated version of my app for the major


releases?
No. The only reason you would need to submit an updated version of your app for a major release is if your app
is going to be broken in that release. If your app will not be broken, then your latest available version of the app
will be rolled over to that major release.

How frequent should I submit updated versions of my app?


We recommend that you bundle more bug fixes and features so that your app doesn't have to be updated
frequently. This has been voiced by our Business Central customers. They do not want to be constantly updating
their apps in their tenants. We recommend a minimum 1-month app update cadence.

What if I have a critical hotfix?


We treat critical hotfixes with the utmost importance. We do have a process around this. Additional information
on this hotfix process can be found here.

If I make changes to the library app, must I also submit an update for
the AppSource app?
You would upload the updated library app to Partner Center, leave the main app as is, and submit for validation.
We then see that the main app has not changed and only validate the library app.

But wouldn’t I need to change the dependency in my main app’s json


to reference the updated library app file?
No. The version number in the dependency listing in the json file to an app is a minimum version. The main app
is essentially saying, "I need version 1.0.0.1 or greater" of the library app. For example, the AppSource app lists
version 1.0.0.1 for the library app, and that means that it can also use version 1.0.0.2.

Why don't I see the updated version of my app in my sandbox


tenant?
Your tenant is on an older version of Business Central and has not yet been upgraded to the latest version of
Business Central. The latest updated version of your app is only compatible with the latest Business Central
version and later. If you upgrade your tenant to the latest version, you can then update your app.

Is there a good way get the status of the validation as it happens?


Collect telemetry data in Microsoft Azure Application Insights. When you submit an app to AppSource, it starts
an automated validation process. This process ensures the extensions in the app meet the technical
requirements for going live. It goes through many of the same checks described in technical validation. Starting
with version 18.4, if an app's set up for it, telemetry traces for the app submission can be emitted to and
recorded in Application Insights. The data provides immediate details about the success or failure of different
phases of the validation. For more information, see Sending Extension Telemetry to Azure Application Insights
and Analyzing AppSource Submission Validation Trace Telemetry..

See also
FAQ about Managing and Submitting your Business Central Offer
FAQ about Library & Dependency Apps in Business Central
Update Lifecycle for AppSource Apps FAQ
The Lifecycle of Apps and Extensions for Business Central
FAQ about Managing and Submitting your Business
Central Offer
2/6/2023 • 2 minutes to read • Edit Online

This section contains answers to frequently asked questions about managing the offer in Partner Center when
you submit an app for Business Central.

If I click the Go Live button, does that mean my app will go live to
AppSource?
No. This button is deceiving, and I wish it were worded differently. When you click this button, it triggers our
validation process and puts your app into our validation queue.

What should I know about the Review and publish button?


This is the button you should click when you want to submit your app for validation each time. Once you click
the button, it takes you to a Review and publish page. Make sure all checkboxes are marked on that page. This
pulls in all changed data into our validation queuing system properly.

I only made marketing changes. Will my app have to go through


technical validation?
No. If you do not change your app in a submission, we skip technical validation.

Is there a good way get the status of the validation as it happens?


Collect telemetry data in Microsoft Azure Application Insights. When you submit an app to AppSource, it starts
an automated validation process. This process ensures the extensions in the app meet the technical
requirements for going live. It goes through many of the same checks described in technical validation. Starting
with version 18.4, if an app's set up for it, telemetry traces for the app submission can be emitted to and
recorded in Application Insights. The data provides immediate details about the success or failure of different
phases of the validation. For more information, see Sending Extension Telemetry to Azure Application Insights
and Analyzing AppSource Submission Validation Trace Telemetry..

See also
FAQ about Updating your Business Central App
FAQ about Library & Dependency Apps in Business Central
Update Lifecycle for AppSource Apps FAQ
The Lifecycle of Apps and Extensions for Business Central
Marketing Validation FAQ
2/6/2023 • 2 minutes to read • Edit Online

Where do I state the countries, editions and languages that my offer


supports?
You're required to state the countries, editions and languages that your offer supports in the bottom of your
offer’s description text. You can use the following format:
Suppor ted Editions:
The app supports the Essentials and Premium Editions of Microsoft Dynamics 365 Business Central.
Suppor ted Countries:
Canada, Mexico and United States
Suppor ted Languages: This app is available in English (United States) and Spanish (Mexico).

Do you have any tips and tricks for what I should write in the
description text?
Yes. We have detailed guidelines and good advice about that here.

How do I refer correctly to the product?


When you mention the product, both throughout your description text, and in your marketing material, you
need to refer to the product, in the following way:
First mentions: Microsoft Dynamics 365 Business Central
Secondar y mentions: Dynamics 365 Business Central
Subsequent mentions: Business Central
Therefore, you can't use any abbreviations such as “MS Dyn 365 BC” or “Microsoft Dynamics NAV”.

What are the requirements for my offer’s help and support page?
You're required to submit two distinct pages for support and help that is, they cannot be the same. You can see
what you have to include on both pages in the table below.

H EL P SUP P O RT

Learning material such as FAQs, step by step guides, video At least two contact options (for example, e-mail, phone,
tutorials, webinars etc. chat) and a defined SLA for how much time it takes before
you answer to support inquires.

Can I use the Microsoft Dynamics 365 Business Central logo?


No, you can't use the Business Central logo, as it’s a Microsoft trademarked logo. However, you can use the “Get
it from Microsoft AppSource” badge, which you can find here.

See Also
Marketing Validation Checklist
Update Lifecycle for AppSource Apps FAQ
2/6/2023 • 5 minutes to read • Edit Online

Please see the following sections for frequently asked questions regarding updating apps on AppSource.

I want to submit an updated version of my app. What is the process


for that?
For any updated version of your app (small or large changes), you follow the same submission as your original
version. It must go through the same validation process. The following are the steps that you must follow:
Increase the version number of your app within its json/manifest file.
Do not change the app’s AppID within its json/manifest file. That needs to remain the same for life of the app
Include an upgrade codeunit and ensure that it works.
Upload the app file to your existing Partner Center offer.
In Partner Center, edit the version field to match what is now in your updated app file.
Make any other edits in Partner Center as needed.
Submit for validation.
Validation takes place as normal (against current production version of Business Central at time of
submission):
Code review is needed for avoiding violations and ensuring requirements are met.
Test validation is scaled back for updated versions.

What happens when my updated app passes validation?


The app is checked into our service and becomes the active version for that current production release of
Business Central. If a tenant is already upgraded to the current release, they can install this updated version of
your app.

Does Microsoft now update my app (to this latest updated version)
on all tenants that already have a previous version?
Microsoft will only force update apps during the 2 major releases (release wave 1 and 2). For these releases,
each tenant will have their AppSource apps force updated to the latest available versions in our service.

How do I update the apps on my tenant for minor releases then?


If a tenant wants to update the apps on their tenant during the minor releases, the tenant admin needs to handle
this. Here are the steps you follow to update your apps:
Login to your Business Central Web client instance.
Navigate to the Extension Management page.
Find the app and uninstall it.
Reinstall the app.
That gives you the latest available version in our service.
NOTE
If a per-tenant extension contains breaking changes, it is possible to force an update by using the Force option on the
Extension Management page. For more information, see Uploading a Per-Tenant Extension (PTE).

How often should I submit updates of my app?


Our recommendation is to pack more bug fixes and features into less frequent updates. Try to avoid frequent
submissions containing very few changes. Being on a more frequent cadence than Business Central (monthly) is
not advised. This leads to lower churn to production tenants.

What if a customer reports a critical bug in my app and needs an


immediate hotfix version of my app?
We have automated a lot of things and most of the submissions are now processed within one business day.
The technical validation of the app is fully automated so you will know within a few minutes (hours in the worst
case) if your app passed the validation or not. Once your app has passed the certification stage, it is
automatically published to Business Central and becomes available for your customers.
Before submitting your apps in Partner Center, our recommendation is to make sure you fulfilled all the
requirements in the technical validation checklist, including running the self-validation.

Do you have any tips for us when submitting updates of our app?
Yes, we have some valuable tips we would like to share. These are tips that can save you time in the validation
process. They will help lead to fewer (and possibly zero) failures during validation. Most importantly; they will
lead to fewer issues being found in production by customers.
Follow the checklist, for more information see Technical Validation Checklist. The checklist is ever evolving
and requirements might change or be added. You might miss something from the checklist, leading to
validation failure and delaying the passing of your updated app.
Follow the technical validation FAQ, for more information see Technical Validation FAQ. We are regularly
updating it based on the questions and support cases raised by partners.
Use AppSourceCop, for more information see Using the Code Analysis Tool. This helps to catch any missing
prefix/suffix and DataClassification. Too often we see these fail the updated versions of apps.
Sign your app. This fails many app validations. We try to publish the app during validation and it is not
properly code-signed leading to failure to publish.
Publish and install your app. This is another big validation failure we see too often.
Test your app’s functionality with 100% coverage. You are the expert on the app and know it best. If you are
only testing a small percentage of your app, customers will most likely find issues resulting in you having to
update your app more often. And if customers are the ones finding your app issues, they may decide to
uninstall it. You should have a vested interest in providing a quality app.
Test the upgrade of your app. upgrade from the previous version to this latest. Your updated app will not pass
validation until the upgrade works. If it fails in our validation, we will return it to you, leading to a delay in it
going to our service.
Collect telemetry data in Microsoft Azure Application Insights. When you submit an app to AppSource, it
starts an automated validation process. This process ensures the extensions in the app meet the technical
requirements for going live. It goes through many of the same checks described in technical validation.
Starting with version 18.4, if an app's set up for it, telemetry traces for the app submission can be emitted to
and recorded in Application Insights. The data provides immediate details about the success or failure of
different phases of the validation. For more information, see Sending Extension Telemetry to Azure
Application Insights and Analyzing AppSource Submission Validation Trace Telemetry..

NOTE
The tips that we provide above are for your benefit to pass validation the first time through each submission. And to
emphasize these points, think of the delays that can arise when you don't follow these tips. If you submit, it can take a
couple days before we validate the app. Once we validate it, if all is good, it should pass quickly. If we find issues that lead
us to fail the validation, we send the app back to you as you have to make fixes. It could then take you days to properly
fix. Next time you submit, your app does not go to the front of the queue. It begins at the bottom again which means it
could be another couple days before we validate it again. By following our tips above, you can avoid those delays. Spend a
bit more time up front finding those issues yourself, leading to a quicker path to our service.

See Also
Retaining table data after publishing
Checklist for Submitting Your App
Upgrading Extensions
Using the Code Analysis Tool
FAQ About the Windows Client and Business
Central
2/6/2023 • 5 minutes to read • Edit Online

The first releases of Business Central on premises included an installed client derived from Dynamics NAV.
Starting with 2019 release wave 2, this legacy component, referred to as "the Windows client", will no longer be
available for Business Central. Find answers for some of the most common questions here.

I have heard "modern clients only". What is this about?


Businesses and users want to be reassured that only the newest, most advanced, and up-to-date tools are being
used to access their data. With Business Central 2019 release wave 2, released October 2019, users switch to the
modern experience in the browser ("the web client"), the Android or iOS mobile apps, or the Windows 10
desktop app, which are available through the respective stores.
Connecting the Windows client to Business Central is not supported in Business Central 2019 release wave 2
and onwards.

Why is Microsoft discontinuing the Windows client?


Our customers must feel comfortable that the tools they use are fit for new hardware, operating systems, and
changing environments. We have accelerated our investment in speed and productivity features for the modern
clients, thereby achieving a major milestone in its transformation into a world-class desktop experience for both
new and expert users.
While the Windows client was inherently bound to the Windows operating system, the modern clients allow us
to reach more customers and more users within an organization, no matter their platform or device of choice.
The latest technologies allow us to innovate at a rapid pace and respond to accelerating compliance
requirements, the changing technology landscape, and requests from the community. In addition, the lower
installation footprint on client devices makes it easier for IT departments and hosters to maintain and support
their user base.

When is the Windows client discontinued in Business Central?


From October 2019 , with Business Central 2019 release wave 2.
It was first announced in 2018 at various conferences and then with a detailed timeline earlier in 2019. For more
information, see Business Central April 2019 Update and the road ahead.

Will the Windows client still be supported in older releases of


Business Central and Dynamics NAV?
Yes. You can safely continue to use the Windows client on premises and receive support as long as you follow
the lifecycle policy for your on-premises installations of Business Central. For more information, see Lifecycle
FAQ - Dynamics.
The Windows client remains suppor ted for the Business Central April 2019 release and all earlier releases of
Business Central on premises and Dynamics NAV, in accordance with the support lifecycle process.
Does this impact me if I use Business Central online?
No. This change only impacts on-premises installations because the Windows client was only available on
premises.

Does this impact me if I use Business Central on premises?


Yes. When you choose to upgrade to Business Central 2019 release wave 2 or later, you must switch to access
Business Central using one of the modern clients. The most popular choice on desktop computers is the web-
browser client where your browser is pointing to an on-premises web server using a URL, such as this example
(not active): https://myserver.mydomain.com/BC170

What if I really want to have an installable component or at least an


icon on my desktop?
You can always add a browser shortcut on your desktop or pin the web page with Business Central to your
Windows task bar. Alternatively, the Business Central Windows 10 desktop app, which is available from
Microsoft Store, is a great way to access Business Central both online and on-premises. To get the app, go to
Microsoft Dynamics 365 Business Central in the store.

How does this impact mobile?


There is no impact on mobile apps for Business Central as they are already part of the modern-client family.
For more information about the mobile apps, seeGetting Business Central on Your Mobile Device.

Can I still work with Business Central data in Excel?


Yes. There are multiple ways to work with Business Central and Excel, including the following:
The Open in Excel feature that downloads any list as an Excel file for your processing or reporting
The Edit in Excel feature that allows you to edit almost any list-based data in Excel and publish it back to
Business Central
For more information, see Viewing and Editing in Excel From Business Central. For instructions on how to
configure it for on-premises, see Setting up the Excel Add-In for Editing Business Central Data.
Note that the legacy, COM-based Excel plugin that used to be included on the installation media is no longer
supported.

Can I still use the same Outlook add-in?


Yes. This change does not impact the Outlook add-in. In fact, the modern Outlook add-in is based on the same
familiar web experience. For more information, see Using Business Central as your Business Inbox in Outlook.

What happened to C/SIDE, the legacy development environment?


In line with the retirement of the Windows client, Business Central 2019 release wave 2 marks a milestone as
the first release without the legacy development environment (also known as C/SIDE). The modern developer
experience, which is based on Visual Studio Code and the new AL language, supports developing large apps,
such as the base application from Microsoft.
Therefore, C/SIDE is discontinued for Business Central going forward. Partners enjoy tremendous productivity
and performance gains after moving to the newest tools. For more information, see Development in AL.
Which features are available in the modern clients and where can I
find the roadmap?
Business Central is a highly adaptable modern business management solution. It is rich in features and options
and is continuously being enhanced. The roadmap is best represented by the release plans, which are updated
every six months. For more information, see Overview of Dynamics 365 Business Central 2019 release wave 2.

See Also
FAQ for Developing in AL
Features not implemented in on-premises deployments of Dynamics 365 Business Central
Business Central Component and System Topology, Additional Components
Software Lifecycle Policy and Dynamics 365 Business Central On-Premises Updates
Dynamics 365 Business Central Compliance
FAQ for Dynamics 365 Update Policies
Dynamics 365 Resources
Welcome to Dynamics 365 Business Central
FAQ about Migrating to Business Central Online
from On-Premises Solutions
2/6/2023 • 5 minutes to read • Edit Online

This section contains answers to frequently asked questions about migrating from on-premises solutions to
Business Central online.

TIP
Check the tips in this article if your organization is not yet ready to migrate to Business Central online but are thinking
hard about it. For more information about migration, see Migrate On-Premises Data to Business Central Online.

Which products and versions are supported?


You can use the built-in migration tools to migrate data to Business Central online from specific product
versions. The on-premises solution must use SQL Server 2016 or a later version, and the database must have
compatibility level 130 or higher. Currently, you can migrate to Business Central online from the following
products:
Dynamics GP 2015 and later versions
Business Central on-premises
Currently, you can migrate to Business Central online from the earlier versions 14 through 20. For an
indication of compatibility across minor versions, see here. You can also switch to online from the current
version (21).
If you are currently on a version of Dynamics NAV, you must upgrade to Business Central on-premises, and then
switch to Business Central online. For more information, see Upgrading from Dynamics NAV to Business Central
online.
System requirements
To migrate to Business Central online, the on-premises solution must use SQL Server 2016 or a later version,
and the database must have compatibility level 130 or higher. The on-premises solution must also be one of the
supported versions.
For comparison, see the System Requirements for Dynamics 365 Business Central (on-premises) 2021 Release
Wave 1 and subsequent versions.

How is my on-premises data migrated to my Business Central online


tenant?
Data is migrated using an Azure service called Azure Data Factory (ADF). ADF is a service that is always running
within the Business Central online service manager. When you start the cloud migration, a data pipeline is
created in the ADF service so that data can flow from your on-premises solution to your Business Central online
tenant. If your data source is a local SQL Server instance, you'll also be asked to configure a self-hosted
integration runtime (SHIR). The runtime is installed locally and manages the communication between the cloud
services and your on-premises data without opening any ports or firewalls.
Are there any limits on the amount or type of data that will migrate?
There are no restrictions on the type of data that can be migrated. By default, Business Central customers can
use up to 80 GB of database storage capacity across all their environments (production and sandbox). This limit
means that the sum of database capacity usage across all of their environments must not exceed 80 GB. If a
tenant exceeds this limit, Microsoft restricts administrative actions that create additional environments.
Exceeding the storage limit will not interrupt transaction processing within the existing environments.Some
businesses have unique scenarios that may require additional storage. For those organizations that need more
space, there's an option to purchase extra database capacity.
We recommend that you reduce the number of companies that you're migrating data for in each migration run.
You can specify which companies to include in the migration in the assisted setup wizard.
If you want to add more companies after the first selection of companies, you can add more companies in the
Cloud Migration Management page in Business Central online. For more information, see Run the tool
multiple times.
If you're looking at migrating databases larger than 80 GB, we recommend that you contact the support team
and work with them to make sure that the migration is successful. If needed, you can also purchase more
storage. For more information, go to Managing Capacity.

Is my SQL connection string required to set up the connection?


Yes. The SQL connection string is passed to Azure Data Factory, where it's encrypted and delivered to your Self-
Hosted Integration Runtime. The connection string is used to communicate with your SQL Server instance
during the data replication process. For more information, see How do I find my SQL connection string?.

How do I find my SQL connection string?


Find the connection string to your SQL database in SQL Management Studio or Visual Studio. The user name
and password defined in the connection requires a SQL Authenticated user name/password. Your connection
string will look something like this:
Server=tcp:{ServerName},1433;Initial Catalog={DatabaseName};Persist Security Info=False; User ID=
{UserName};Password=
{Password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;

How do I find the Integration Runtime name?


Find the Integration Runtime name in the Microsoft Integration Runtime Manager, which you can find in your
Windows system tray or by searching for the program. You must type the name. You won't be able to copy and
paste the name.

I'm a hosting partner - do I need to configure the Self-Hosted


Runtime Service for each tenant?
No, there's no limit on the number of tenants that can be added to your Self-Hosted Integration Runtime. Each
added tenant will have a dedicated pipeline created.

Will data from tables with code customizations migrate?


No, only tables that are available in both your on-premises solution and your Business Central online tenant will
migrate. Any customization must be made into an extension and installed on both your on-premises solution
and your Business Central online tenant to replicate.
Yes, but it requires that someone defines tables mappings to move the customized fields. For more information,
go to Define Migration Table Mappings.

Why are my permissions restricted in the Business Central online


tenant?
When you connect your on-premises solution to Business Central online as part of the migration, all existing
users are automatically added to the Intelligent Cloud user group, unless they have the SUPER permission set. In
this configuration, your on-premises solution is the master where all business transactions take place. The
Business Central online environment is read-only, and the data is used to generate intelligent business insights
based on your on-premises data for you. We restrict permissions to prevent users from accidentally entering
transactions or updating master records only to have that information overwritten and lost when data
replication takes place. Once the migration is complete, you can assign the relevant permissions to all users and
stop using your on-premises solution.

Will my on-premises users and permissions replicate?


No. Since you aren't required to configure your on-premises solution with Azure Active Directory (Azure AD), we
can't guarantee a mapping between on-premises users and users in your Business Central online tenant.
Business Central online requires Azure AD accounts, and users must be manually added. All permissions must
be granted in the Business Central tenant, independent from your on-premises permissions.
For more information, see Managing Users and Permissions.

Is the data replication only one way?


Yes, data is only replicated from the on-premises solution to your Business Central online tenant for the
purposes of migration. Once you start using Business Central online, you must stop using your on-premises
solution.

Should I uninstall all my Business Central extensions?


No. But if your cloud migration includes data upgrade of a large amount of data, we recommend that you
uninstall the extensions that that include any data to move. It will speed up the upgrade and overall cloud
migration process. You can reinstall the extensions after the migration.

See also
Troubleshooting Cloud Migration
Migrating On-Premises Data to Business Central Online
Update 21.4 for Microsoft Dynamics 365 Business
Central online 2022 release wave 2
2/6/2023 • 2 minutes to read • Edit Online

The update is coming soon. Stay tuned!

Would you like to know what has changed in update 21.4? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article and the downloads here.

Feature changes
Reuse launch configurations across workspace projects

Service releases in February (will be available to your environments


without updating to 21.4)
Get more visibility into service interruptions
Get more, better communications as admin
Restore deleted environments
Restore environments to point in time
Restrict traffic on system integrations with service tags

Localization updates
C O UN T RY F EAT URE DESC RIP T IO N

Mexico [CDFI] New Electronic Document Electronic invoices in Mexico will have
Status for cancelling a stamp from a different statuses when they're being
Posted Sales Invoice cancelled. When a business cancels the
stamp on an invoice, Business Central
shows an In Progress status until
someone from SAT either approves or
rejects the cancellation. The status that
shows next depends on what’s done
on the SAT side. If SAT approves the
cancellation, the status of the
electronic invoice becomes cancelled.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2022 release wave 2 (release from October 2022 through March 2023), find the link to the release plan
here.
Upgrade to 21.4
Please note that new customers will automatically get the latest builds of Business Central (21.4). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Impor tant: Take action before March 1 to retain your delegated admin access to your customers
Earlier this year, Microsoft Partner Center introduced Granular Delegated Administration Privileges (GDAP) as
replacement for Delegated Administration Privileges (DAP) to enable partner-customer relationships that are
time-bound and have more granular access rights. The timeline to migrate your existing DAP relationships to
GDAP has been moved to March 1, 2023. If you do not take action by this date you will lose access to your
customers' Business Central environments. Please refer to the Partner Center announcement here.
Release plan for 2023 release wave 1 is now live
The release plan for Business Central 2023 release wave 1 is live! Check out the product overview and what's
new and planned for Business Central here: https://aka.ms/BCReleasePlan.
Join us for updates on LinkedIn!
Follow the new company page for Microsoft Dynamics 365 Business Central on LinkedIn. We’ll share updates,
announcements, and other “good to know” stuff. Join us here.
Business Central newsletter for par tners
Yay! We're doing quarterly newsletters for Business Central partners. Each newsletter contains a summary of
relevant information related to Business Central. You can find it on aka.ms/BCNews.
Upcoming Business Central Office Hours Calls
In January and February, we will be hosting the following calls, which you can already register for today:
Februar y 7: Power Platform integrations
March 14: Onboarding your customers to Business Central
Register and stay tuned for upcoming calls: aka.ms/BCOfficeHours. Watch on-demand recordings:
aka.ms/BCOfficeHoursRecordings.
Discover resources on aka.ms/BCAll
Are you looking for relevant resources? Find it all in this article aka.ms/BCAll and remember to bookmark it!
Update 21.3 for Microsoft Dynamics 365 Business
Central online 2022 release wave 2
2/6/2023 • 4 minutes to read • Edit Online

Would you like to know what has changed in update 21.3? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article and the downloads here.

Feature changes
Reuse launch configurations across workspace projects
Media/image support for Business Central connectors
Power Apps and Power Automate support for document attachments
Reverse payment reconciliation journal entries
Access attachments on additional list pages
Scroll through more records in lists

Localization updates
C O UN T RY F EAT URE DESC RIP T IO N

Switzerland Enabling QR-Bill file that does not Swiss companies now can use QR bills
report Amount and other information with and without invoice amounts. If
user chooses option with amount,
system will automatically populate the
Amount field, but if user chooses
option without amount, the Amount
field will be editable and user can
populate it manually.

France, United Kingdom Intrastat localization extensions New Intrastat feature is now available
in France and United Kingdom.

W1 Add support of Service Documents to Service Declaration feature has been


Service Declaration extended, so now except purchase and
sales documents, system also uses
Service document for reporting export
of services.

W1 Adding Supplemental Unit fields to If user defines Supplemental Unit of


Tariff Numbers as default Measure for specific Tariff Number (for
usage in Intrastat), it will be used in all
Items as default Supplemental Unit of
Measure.
C O UN T RY F EAT URE DESC RIP T IO N

W1 Changing VAT date with more entries When users have more VAT Entries for
for one document one document with different VAT
percentages, and they want to change
VAT date, they need to do only on one
entry and the system will update to
the other entries for the same
document.

W1 Disabling VAT date functionality fully or Users now can choose to use full VAT
partially date functionality or just partially
without changing VAT dates in posted
entries and documents. And
eventually, users can choose not to use
VAT date functionality, hiding and
making noneditable VAT fields from UI.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2022 release wave 2 (release from October 2022 through March 2023), find the link to the release plan
here.

Upgrade to 21.3
Please note that new customers will automatically get the latest builds of Business Central (21.3). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Reverse payment reconciliation journal entries
With 21.3. you can reverse payment reconciliation journals that were used to also post a bank reconciliation.
With 21.4, we will enable reversal of regular payment reconciliation journals.
Shopify connector becomes extensible: Stock calculation
Shopify Connector has been non-extensible, but we're changing that. We're offering a few points of extensibility.
We'll keep the number of points to a minimum so that we can follow the rapid development on the Shopify side
without introducing breaking changes.
We are opening for extensibility for specific scenarios, based on feedback from our partners and customers
starting with Stock calculation .
For more details, please follow this repository on GitHub. Note that even though extensibility is limited, you can
submit improvements directly.
Power Apps and Power Automate suppor t for media/image and document attachments
Business Central connector (online only) for Power Platform and Azure Logic Apps has been enhanced with new
capabilities and actions to allow makers to access rich data from Business Central. Note that the updated
connector is rolling out to all Azure regions now and is backward compatible with latest Business Central online
versions (including version 21.3 discussed here), but in order to take advantage of these new capabilities in
Power Automate flows the user needs to create a new flow using the new action discussed here.
You can still watch the Business Central Launch Event recordings
We have 15+ What's New sessions and recorded Q&As available throughout January 2023. If you didn't watch
them yet, you can still go to aka.ms/BCLE to sign up. In November, two new sessions have been published for
the following topics: Embed Business Central in Teams tabs and Access Business Central with your Microsoft 365
license.
AL-Go for GitHub version 2.2
Version 2.2 of AL-Go for GitHub has been released with improved multi-project support and a few fixes in the
Pull Request workflow. See what has been added and changed in the v2.2 column in [aka.ms/AlGoRoadmap].
Impor tant: Take action before March 1 to retain your delegated admin access to your customers
Earlier this year, Microsoft Partner Center introduced Granular Delegated Administration Privileges (GDAP) as
replacement for Delegated Administration Privileges (DAP) to enable partner-customer relationships that are
time-bound and have more granular access rights. The timeline to migrate your existing DAP relationships to
GDAP has been moved to March 1, 2023. If you do not take action by this date you will lose access to your
customers' Business Central environments. Please refer to the Partner Center announcement here.
Business Central newsletter for par tners
Yay! We're doing quarterly newsletters for Business Central partners. Each newsletter contains a summary of
relevant information related to Business Central. You can find it on aka.ms/BCNews.
Upcoming Business Central Office Hours Calls
In January and February, we will be hosting the following calls, which you can already register for today:
Januar y 17: AL-Go for GitHub
Januar y 24: Onboarding your customers to Business Central
Februar y 7: Power Platform integrations
Register and stay tuned for upcoming calls: aka.ms/BCOfficeHours. Watch on-demand recordings:
aka.ms/BCOfficeHoursRecordings.
Discover resources on aka.ms/BCAll
Are you looking for relevant resources? Find it all in this article aka.ms/BCAll and remember to bookmark it!
Update 21.2 for Microsoft Dynamics 365 Business
Central online 2022 release wave 2
2/6/2023 • 4 minutes to read • Edit Online

Would you like to know what has changed in update 21.2? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article and the downloads here.

Feature changes
Use default attachments in email sent from Business Central
Easily comply with email sending limits through email throttling
Move custom fields to extensions during cloud migration
Integrated session using Service-to-Service (S2S) authentication can now schedule tasks

Localization updates
C O UN T RY F EAT URE DESC RIP T IO N

United States IRS 1099 Form Update for 2022 With this release, Form 1099 in the
United States has been updated to
fulfill 2022 year requirements for
reporting to IRS.

Mexico Extending CFDI with foreign trade With new release Business Central will
include the information to fill the
foreign trade details in the file, which is
mandatory by the SAT if a customer
performs an export to a foreign
country.

France Service Declaration (DES) In some France, authorities require


reporting for exporting services to the
other EU countries. This feature
enables collecting EU service’s
intertrade and its reporting to the
authorities. This feature is named as
Service Declaration or DES, and with
this release it is enabled in France.
Service Declaration is created as an
extension.
C O UN T RY F EAT URE DESC RIP T IO N

The Netherlands Added configuration for Electronic Tax Setup is extended so now users have
Declaration the endpoints setup under the new
“Endpoints” tab instead of hardcoded
endpoints. This change also includes
an upgrade Codeunit that fills the
value in this setup for the existing
tenants.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2022 release wave 2 (release from October 2022 through March 2022), find the link to the release plan
here.

Upgrade to 21.2
Please note that new customers will automatically get the latest builds of Business Central (21.2). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Use Ser vice Suppor t Administrator role to manage suppor t requests on behalf of your customers
To better support this principle and align with the expectations of our customers, especially the Business Central
customers working with other Dynamics 365 products, together with the Power Platform Admin Center team
we introduce support for the Service Support Administrator role which gives access to manage support
requests on the customer's behalf. If you need to log support tickets on behalf of your customers using Power
Platform Admin Center, make sure you request this role in your GDAP relationship.
You can still watch the Business Central Launch Event recordings
We have 15+ What's New sessions and recorded Q&As available throughout January 2023. If you didn't watch
them yet, you can still go to aka.ms/BCLE to sign up. In November, two new sessions have been published for
the following topics: Embed Business Central in Teams tabs and Access Business Central with your Microsoft 365
license.
AL-Go for GitHub version 2.2
Version 2.2 of AL-Go for GitHub has been released with improved multi-project support and a few fixes in the
Pull Request workflow. See what has been added and changed in the v2.2 column in [aka.ms/AlGoRoadmap].
Impor tant: Take action before March 1 to retain your delegated admin access to your customers
Earlier this year, Microsoft Partner Center introduced Granular Delegated Administration Privileges (GDAP) as
replacement for Delegated Administration Privileges (DAP) to enable partner-customer relationships that are
time-bound and have more granular access rights. The timeline to migrate your existing DAP relationships to
GDAP has been moved to March 1, 2023. If you do not take action by this date you will lose access to your
customers' Business Central environments. Please refer to the Partner Center announcement here.
Business Central Performance toolkit VSCode extension
The Performance Toolkit extension is built for Independent Solution Vendors (ISVs) and Value Added Resellers
(VARs) who develop vertical solutions and customize Business Central for their customers. Because things
change between released versions, it's important that ISVs and VARs can test the performance of their solutions
to ensure that new versions don't introduce performance regressions when the volume of users grows. To help,
the Performance Toolkit lets developers simulate workloads in realistic scenarios to compare performance
between builds of their solutions. The Performance Toolkit extension helps answer questions such as, "Does my
solution for Business Central support X number of users doing this, that, and the other thing at the same time?".
Learn more here.
Business Central newsletter for par tners
Yay! We're doing quarterly newsletters for Business Central partners. Each newsletter contains a summary of
relevant information related to Business Central. You can find it on aka.ms/BCNews.
Upcoming Business Central Office Hours Calls
In December and January, we will be hosting the following calls, which you can already register for today:
December 13: Troubleshooting performance problems
Januar y 17: Exporting your Dynamics 365 Business Central data to the Azure Data Lake Storage
Januar y 24: Onboarding your customers to Business Central
Register and stay tuned for upcoming calls: aka.ms/BCOfficeHours. Watch on-demand recordings:
aka.ms/BCOfficeHoursRecordings.
Discover resources on aka.ms/BCAll
Are you looking for relevant resources? Find it all in this article aka.ms/BCAll and remember to bookmark it!
Update 21.1 for Microsoft Dynamics 365 Business
Central online 2022 release wave 2
2/6/2023 • 4 minutes to read • Edit Online

Would you like to know what has changed in update 21.1? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Access Business Central with your Microsoft 365 license
Embed Business Central in Teams tabs
Auto-Save as you work: due to popular demand, administrators can now choose to turn on or off the new
auto-saving behaviour using Feature Management
Business Central is available in 11 more countries
Accessibility declaration for Italy available
Use SharePoint Connector module in System Application to build integration between Business Central and
Sharepoint
Use multiline text fields with Word mail merge
Sync users based on environments security group

Localization updates
C O UN T RY F EAT URE DESC RIP T IO N

Belgium Vendor Name as a column in EB Vendor Name now exists in Belgium


Payment Journal local EB Payment Journal, the same as
in W1 Payment Journal feature.

W1 Services Declarations [BE] F01DGS Belgian authorities require reporting


Declaration for exporting services to the other EU
countries and this includes the
F01DGS form for Belgium. Even
primarily required for Belgium market,
this feature is available as an extension
and can be used in all countries.
Reporting is configurable, so it won't
have a hard-coded format for export.
It works with the Items (Type=Service),
Resources, and Item Charges as
services in both purchase and sales
documents.
C O UN T RY F EAT URE DESC RIP T IO N

United States IRS 1099 All IRS 1099 form printouts are
updated accordingly with 2022
requirements. When users open the
1099 Form Boxes page, they will see
the notification about update to 2022
release. They can schedule an upgrade
and when it is finished, new reports
will be available for usage.

The Netherlands Electronic Tax Declaration Setup Previously used hardcoded endpoints
for electronic tax declaration have been
moved to the setup under the new
“Endpoints” tab, so users now can
configure endpoints manually. It will be
deployed to 21.1 tenants. But for
them, the upgrade would not be
executed, and they will see all the
values blank. But Digipoort solution
still would work and take the
hardcoded values if there are no values
in the setup. For 21.2 the system will
automatically run an upgrade.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2022 release wave 2 (release from October 2022 through March 2022), find the link to the release plan
here.

Upgrade to 21.1
Please note that new customers will automatically get the latest builds of Business Central (21.1). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
You can still watch the Business Central Launch Event recordings
We have 15+ What's New sessions and recorded Q&As available throughout January 2023. If you didn't watch
them yet, you can still go to aka.ms/BCLE to sign up. In November, two new sessions have been published for
topics: Embed Business Central in Teams tabs and Access Business Central with your Microsoft 365 license.
Business Central at Ignite
At the Microsoft Ignite event on October 12, we unveiled new and exciting collaboration features for SMBs that
usher in a new era for collaborative applications. Check out the announcements in the Microsoft Ignite Book of
News and Dynamics 365 blog to learn how our customers can leverage 2022 release wave 2 to work smarter,
increase team performance, and quickly adapt their digital collaborative spaces to make data-driven decisions.
Impor tant: Take action before March 1 to retain your delegated admin access to your customers
Earlier this year, Microsoft Partner Center introduced Granular Delegated Administration Privileges (GDAP) as
replacement for Delegated Administration Privileges (DAP) to enable partner-customer relationships that are
time-bound and have more granular access rights. The timeline to migrate your existing DAP relationships to
GDAP has been moved to March 1, 2023. If you do not take action by this date you will lose access to your
customers' Business Central environments. Please refer to the Partner Center announcement here.
New versions of the Business Central mobile app for Android and iOS
New, updated 3.8.xxxx versions of the Business Central mobile app for Android and iOS have been released
featuring support for additional Business Central localization, some minor improvements an fixes and newest
requirements from mobile OS releases. Please note the required minimum supported versions of both
iOS/iPadOS and Android (currently Android 10 is required for Business Central mobile app). Please keep your
mobile app updated by downloading the update. Links:
iOS/iPadOS on App Store: https://go.microsoft.com/fwlink/?LinkId=734847
Android on Play Store: https://go.microsoft.com/fwlink/?LinkId=734849
Business Central newsletter for par tners
Yay! We're now doing quarterly newsletters for Business Central partners. Each newsletter will be a summary of
relevant information related to Business Central and you'll be able to find it on aka.ms/BCNews.
Upcoming Business Central Office Hours Calls
In November, we will be hosting the following calls, which you can already register for today:
November 15: Non-deductible and partly deductible VAT
November 22: Access Business Central using your Microsoft 365 license
Register and stay tuned for upcoming calls: aka.ms/BCOfficeHours. Watch on-demand recordings:
aka.ms/BCOfficeHoursRecordings.
Discover resources on aka.ms/BCAll
Are you looking for relevant resources? Find it all in this article aka.ms/BCAll and remember to bookmark it!
Update 20.6 for Microsoft Dynamics 365 Business
Central online 2022 release wave 1
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 20.6? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2022 release wave 1 (release from April 2022 through September 2022), find the link to the release plan
here.

Upgrade to 20.6
Please note that new customers will automatically get the latest builds of Business Central (20.5). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Join us for the Business Central Launch Event on October 10-12, 2022
Dynamics 365 Business Central 2022 release wave 2 will be released on October 3, after which new customers
will be able to sign up for version 21 of Business Central. To learn all about what's new in the latest release, we're
again bringing the latest innovations for Business Central to you via an all-access digital experience.
The Business Central Launch Event will take place from October 10-12, 2022. During the three days, you’ll be
able to watch sessions, ask questions and participate in live Q&As. After October 12, all sessions will be
available on-demand until January 2023.
Register now : aka.ms/BCLE
Impor tant: Take action before October 31 to retain your delegated admin access to your
customers
With this Partner Center announcement earlier this year, Microsoft introduced the Granular Delegated Admin
Privileges (GDAP) feature. GDAP addresses various security concerns by allowing customer administrators to
provide partners a proper level of time-bound access to their tenants.
The Partner Center team has now announced the timeline by which you need to migrate your customer
relationship to GDAP. Please make sure to read this new Partner Center announcement for more details about
milestone dates and the transition plan, as well as about the tools Microsoft provides to facilitate this process.
To manage Dynamics 365 Business Central customers via GDAP we recommend requesting the Dynamics 365
Administrator role as the least-privileged role. Read more about which other roles are supported for delegated
administration of Business Central here.
You can watch the GDAP Office Hours recording for Business Central here.
Business Central newsletter for par tners
Yay! We're now doing quarterly newsletters for Business Central partners. Each newsletter will be a summary of
relevant information related to Business Central and you'll be able to find it on aka.ms/BCNews.
Upcoming Business Central Office Hours Calls
In September and October, we will be hosting the following calls, which you can already register for today:
October 4: Get data-driven with Telemetry
November 11: Performance
Register and stay tuned for upcoming calls: aka.ms/BCOfficeHours. Watch on-demand recordings:
aka.ms/BCOfficeHoursRecordings.
Discover resources on aka.ms/BCAll
Are you looking for relevant resources? Find it all in this article aka.ms/BCAll and remember to bookmark it!
Update 20.5 for Microsoft Dynamics 365 Business
Central online 2022 release wave 1
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 20.5? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2022 release wave 1 (releases from April 2022 through September 2022), find the link to the release plan
here.

Upgrade to 20.5
Please note that new customers will automatically get the latest builds of Business Central (20.5). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Impor tant: Take action before October 31 to retain your delegated admin access to your
customers
With this Partner Center announcement earlier this year, Microsoft introduced the Granular Delegated Admin
Privileges (GDAP) feature. GDAP addresses various security concerns by allowing customer administrators to
provide partners a proper level of time-bound access to their tenants.
The Partner Center team has now announced the timeline by which you need to migrate your customer
relationship to GDAP. Please make sure to read this new Partner Center announcement for more details about
milestone dates and the transition plan, as well as about the tools Microsoft provides to facilitate this process.
To manage Dynamics 365 Business Central customers via GDAP we recommend requesting the Dynamics 365
Administrator role as the least-privileged role. Read more about which other roles are supported for delegated
administration of Business Central here.
You can watch the GDAP Office Hours recording for Business Central here.
Plan and prepare for Dynamics 365 Business Central 2022 release wave 2
The preview of Dynamics 365 Business Central 2022 release wave 2 will go live on August 31. Use Microsoft
Collaborate to submit your feedback or to report any potential issues that you discover in the preview. Discover
how to do so here: aka.ms/BCPreview. In addition, we have created a new subgroup on Yammer called Public
Preview 2022 release wave 2, which can be used to share feedback directly with the Microsoft product team or
ask questions related to the preview.
On October 1, 2022, the release will go live. You can discover what's new and planned here:
aka.ms/BCReleasePlan
Business Central newsletter for par tners
Yay! We're now doing quarterly newsletters for Business Central partners. Each newsletter will be a summary of
relevant information related to Business Central and you'll be able to find it on aka.ms/BCNews.
Upcoming Business Central Office Hours Calls
In September and October, we will be hosting the following calls, which you can already register for today:
September 6: Power Automate and Power Platform integrations
September 20: How we secure your data in Business Central
October 4: Get data-driven with telemetry
Register and stay tuned for upcoming calls: aka.ms/BCOfficeHours. Watch on-demand recordings:
aka.ms/BCOfficeHoursRecordings.
Discover resources on aka.ms/BCAll
Are you looking for relevant resources? Find it all in this article aka.ms/BCAll
Update 20.4 for Microsoft Dynamics 365 Business
Central online 2022 release wave 1
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 20.4? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Current user support for the SMTP email connector
Shopify prospects get a great first-run experience

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2022 release wave 1 (release from April 2022 through September 2022), find the link to the release plan
here.

Upgrade to 20.4
Please note that new customers will automatically get the latest builds of Business Central (20.4). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Plan and prepare for Dynamics 365 Business Central 2022 release wave 2
In October 2022, the new release will go live. You can already discover what's new and planned in the release
plan here: aka.ms/BCReleasePlan
Business Central newsletter for par tners
Starting June 2022, we're doing quarterly newsletters for Business Central partners. Each newsletter will be a
summary of relevant information related to Business Central and you'll be able to find it on aka.ms/BCNews.
Discover resources on aka.ms/BCAll
Are you looking for relevant resources? Find it all in this article and remember to bookmark aka.ms/BCAll.
Upcoming Business Central Office Hours Calls
For August and September, we will be hosting the following calls, which you can register for today:
August 23: Excel Layout and reporting
August 30: You know it, so share it in Microsoft Docs for Dynamics 365 Business Central
September 6: Power Automate and Power Platform integrations
Register and stay tuned for upcoming calls: aka.ms/BCOfficeHours. Watch on-demand recordings:
aka.ms/BCOfficeHoursRecordings.
Update 20.3 for Microsoft Dynamics 365 Business
Central online 2022 release wave 1
2/6/2023 • 3 minutes to read • Edit Online

Would you like to know what has changed in update 20.3? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we've gathered some good
to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Improved settings for managing updates (read more here)
New AppSourceCop allowing you to run validation to determine any code hit by obsoleted objects for a
given future version
As continuation for Support inventory pick and warehouse pick operations for jobs, we introduce a To-Job
Bin Code field on the Location Card page to support warehouse pick scenarios. You can also use it in
inventory picks if you prefer a specific bin to be set on a job planning line.

Localization updates
C O UN T RY F EAT URE DESC RIP T IO N

W1 Extended text functionality for VAT In some situations and countries, VAT
clauses Clauses can take more than allowed
number of characters. Because of that
Extended Texts logic is implemented in
the VAT Clauses and this extended text
can be shown on the sales invoice.

Germany Enhancements to Business Data Export Export file will use table and field
file (GDPdU / GoDB) names instead of captions. Also table
and field names won't be limited to 20
characters and it will show full name,
with blanks, dots, etc.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2022 release wave 1 (releases from April 2022 through September 2022), find the link to the release plan
here.

Upgrade to 20.3
Please note that new customers will automatically get the latest builds of Business Central (20.3). If you're an
existing partner/customer, you'll receive an email notification as soon as your environment has been upgraded.
Good to know
A single tile to go to Business Central
During July 2022, we're rolling out a change to online customers where a single Business Central tile in the App
Launcher will be used to access both production and sandbox environments. Learn more here.
UI glitches introduced by recent browser updates
On Wednesday June 29, 2022, Microsoft began rolling out a fix for all Business Central online customers that
addresses UI glitches introduced by a recent Chromium browser update. The fix will also be included in
cumulative updates for supported versions of Business Central on premises. Learn how on premises customers
can fix or work around the issue here.
General availability of the Shopify Connector
In October 2021, we announced a new partnership with Shopify to help our customers create a better shopping
experience. The partnership was designed to better connect the easy-to-use commerce and merchant
experience of Shopify with the comprehensive business management capabilities of Microsoft Dynamics 365
Business Central. The Shopify connector is now available for Business Central online at no extra cost. Existing
customers that have been upgraded to 20.1 or later automatically get the Shopify extension installed. If they
don't need the app, it can be uninstalled by following this guidance. Read the blog, the FAQ, watch the on-
demand session, learn how to get started and view the listing on Shopify App Store.
Action required by July 2022 for Excel Add-in
Starting in July 2022, Microsoft will roll out an update to the Excel add-in that further secures the connection to
Business Central. The update requires that you modify your organization's Azure Active Directory (Azure AD)
configuration so that users can continue using the add-in. This issue impacts all Business Central on-premises
deployments that use the Excel add-in. Learn more here.
Business Central newsletter for par tners
Starting June 2022, we're doing quarterly newsletters for Business Central partners. Each newsletter will be a
summary of relevant information related to Business Central and you'll be able to find it on aka.ms/BCNews.
Discover resources on aka.ms/BCAll
Are you looking for relevant resources? Find it all in this article and remember to bookmark aka.ms/BCAll.
Upcoming Business Central Office Hours Calls
The Business Central office hours calls will be unavailable in July. For August and September, we'll be hosting the
following calls, which you can register for today:
August 23: Excel Layout and reporting
August 30: You know, so share it in the docs for Dynamics 365 Business Central
September 6: Power Automate and Power Platform integrations
Register and stay tuned for upcoming calls: aka.ms/BCOfficeHours. Watch on-demand recordings:
aka.ms/BCOfficeHoursRecordings.
Update 20.2 for Microsoft Dynamics 365 Business
Central online 2022 release wave 1
2/6/2023 • 3 minutes to read • Edit Online

Would you like to know what has changed in update 20.2? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Release and reopen multiple documents

Localization updates
C O UN T RY F EAT URE DESC RIP T IO N

W1 New field, Intrastat Par tner Type , The Intrastat Partner Type field has
on customer and vendor cards replaced the Parter Type field in
Intrastat reporting. Partner Type is
used in SEPA to define the SEPA Direct
Debit Scheme (Core or B2B). Intrastat
Partner Type is used for Intrastat
reporting only. This way, users can
specify different values for the two
fields if they need to. More details
about setup here.

W1 Improvement in creating Intrastat file When the line in Intrastat has


for item with supplementary UOM and supplementary unit of measure,
without weight weight for the item is not necessary.
Now users can create the file even if
they don't have weight for the item on
Intrastat line if this item uses
supplementary unit of measure.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2022 release wave 1 (release from April 2022 through September 2022), find the link to the release plan
here.

Upgrade to 20.2
Please note that new customers will automatically get the latest builds of Business Central (20.2). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.
Good to know
General availability of the Shopify Connector
Last October, we announced a new partnership with Shopify to help our customers create a better shopping
experience. The partnership was designed to better connect the easy-to-use commerce and merchant
experience of Shopify with the comprehensive business management capabilities of Microsoft Dynamics 365
Business Central. The Shopify connector is now available for the online version of Business Central at no extra
cost. Existing customers that have been upgraded to 20.1 automatically get the Shopify extension installed. If
they do not need the app, it can be uninstalled by following this guidance. Read the blog, the FAQ, watch the on-
demand session, learn how to get started and view the listing on Shopify App Store.
A single tile to go to Business Central
We're simplifying access to Business Central online by transitioning to a single app tile starting in June 2022.
Learn more here.
Action required by July 2022 for Excel Add-in
Starting in July 2022, Microsoft will roll out an update to the Excel add-in that further secures the connection to
Business Central. The update requires that you modify your organization's Azure Active Directory (Azure AD)
configuration so that users can continue using the add-in. This impacts all Business Central on premises
deployments that use the Excel add-in. Learn more here.
Changes to the Per-Tenant Extensions Disclaimer
The disclaimer for per-tenant extensions has changed. Find the new Business Central PTE disclaimer here.
Upcoming Business Central Office Hours Calls
Join us for the upcoming office hours call on “Introducing Shopify for Business Central” on June 14 and
“Onboarding your customers to Business Central” on June 21 (Note: we will have two time slots, an early one
and a later one for the two calls). Register and stay tuned for upcoming calls: aka.ms/BCOfficeHours. Watch on-
demand recordings: aka.ms/BCOfficeHoursRecordings.
Business Central Launch Event
If you haven't watched them yet, remember that you still have access to a keynote and 20+ sessions about
what's new in Business Central 2022 release wave 1. You'll hear from product leaders as they share with you the
latest innovations and capabilities to help you confidently move to the cloud and unlock the insights needed to
adapt faster, work smarter, and perform better. Whether you are a business professional, developer, or
consultant at a Business Central partner, get ready to up level your game and drive business transformation.
Register on aka.ms/BCLE
Update 20.1 for Microsoft Dynamics 365 Business
Central online 2022 release wave 1
2/6/2023 • 5 minutes to read • Edit Online

Would you like to know what has changed in update 20.1? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Add action on card and list pages to trigger a chosen flow from Business Central web client
Power Platform and Azure Logic Apps connector for Business Central online no longer in preview
Fraud prevention headers for clients in the UK
Country/regional expansion in 20 new countries

Localization updates
C O UN T RY F EAT URE DESC RIP T IO N

Mexico CFDI Payment version 2.0 Payment receiving will be updated


related with the version 2.0. New fields
are included to identify whether the
payments for the operations covered
by the voucher are subject to tax. A
new section is included with a
summary of the total amounts of the
payments made expressed in national
currency, as well as the taxes that are
transferred.

Spain Posting Date or Document Date to be The user is now able to choose
used as Operation Date between Posting Date or Document
Date, to be used as Operation Date in
the XML sent via SII to the Tax
Authorities.

Denmark; W1 Country code in the VAT Registration In Denmark companies need to use
No. usage for Intrastat reporting different VAT Registration No. models
in Intrastat and Skat.dk (one with
Country Code and another without it).
To avoid issues for Stat.dk clients will
use only value from VAT Registration
No., but for intrastat clients will have
additional configuration with the
following options: VAT Reg. No.,
Country Code + VAT No., VAT No.
without Country Code. This feature is
available on W1.
C O UN T RY F EAT URE DESC RIP T IO N

France Intrastat FR new requirements for DEB For France, Intrastat management
2022 implies to separate the declaration
data for the statistical reporting and
for the fiscal reporting (recapitulative
statement of VAT), once for obligation
level 1 and once for obligation level 4.

Norway Add support of the free text for each This is an improvement of the existing
VAT return line feature. Previously, Business Central
only supported export of a list of the
predefined texts in the field "VAT Note
Code". Now the user can export the file
with added free text for each VAT
return line.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online in 2022
release wave 1 (release from April 2022 through September 2022), find the link to the release plan here.

Get the update


New customers will automatically get the latest update of Business Central (20.1). Admins of existing
environments will receive an email notification as soon as the environment has been updated. For more
information, see Major Updates and Minor Updates for Business Central Online.

Good to know
Shopify Connector
Microsoft is teaming up with Shopify to help our Dynamics 365 Business Central customers create a better
online shopping experience. With update 20.1, the Shopify Connector is available for new customers and for
trial users to try it out. For existing customers, the Shopify connector will become available later in May,
releasing on AppSource and Shopify App Store. Read more here.
Changes to the Per-Tenant Extensions Disclaimer
The disclaimer for per-tenant extensions has changed. Find the new Business Central PTE disclaimer here.
Updated documentation and samples related to Power Automate
Documentation related to Power Automate integration and the new Automate feature has been updated in
May 2022 and is available at aka.ms/BCAutomate. There are also some sample flows published in our github
repository – find it under aka.ms/BCTech. We also recommend watching the What’s new in Business Central and
Power Platform session at he Business Central Virtual Launch Event. Find it on aka.ms/BCLE.
Discover the features for 2022 release wave 1
Discover what's new and planned for Dynamics 365 Business Central 2022 release wave 1. You can find the list
of features here: aka.ms/BCReleasePlan.
Reminder : Avoid an unexpected data upgrade during cloud migration
When you run cloud migration from a previous version of Business Central, one of the process steps is to run
the data upgrade logic to align the migrated data to the format of the current version. We strongly recommend
that you perform this step one time after you have completed the migration of all your customer’s data to the
online environment. If a planned Business Central major or minor update is applied to this environment, the
update will automatically include the upgrade of the data that was migrated by the cloud migration. These
planned updates also turn off cloud migration for the environment. To avoid this situation, and to allow you to
complete the migration and data upgrade for your environment, we recommend that you postpone any
scheduled major and minor updates for the target environment until you have completed cloud migration. You
can postpone updates in the Business Central admin center. For more information, see Managing Updates.
Upcoming Business Central Office Hours Calls
Join us for the upcoming office hours call on “Extending Business Central’s Email Capabilities” on May 24.
Register and stay tuned for upcoming calls: aka.ms/BCOfficeHours. Watch on-demand recordings:
aka.ms/BCOfficeHoursRecordings.
A new update to the Business Central mobile app for iOS and Android
There is a new update for the Business Central mobile app (version 3.7) for iOS and Android available in
respective app stores. This app – as before – handles Business Central online and on-premises and the update is
required for on-premises customers running Business Central 2022 release wave 1.
The legacy Windows desktop app based on UWP technology only suppor ts legacy on-premises
Business Central
Just an update that the Business Central desktop legacy UWP app version 3.6.3101 has been released to the
Microsoft Store - and marked as a mandatory update for Windows users.
From now on users of Windows devices will only be able to use that legacy UWP app to connect to on-
premises Business Central installations v19 or below. For v20 and later on-premises - see next point.
On-premises users of Business Central v20 or later will be able to use the PWA app installed from the
browser directly (see aka.ms/BCPWA for more).
All online Business Central users regardless of the version can use the new PWA app installed from the
browser OR from the Microsoft store (again, see aka.ms/BCPWA for more).
It is recommended to switch to the PWA technology as this is where customers can benefit fully from all web
client features.
Update 19.5 for Microsoft Dynamics 365 Business
Central online 2021 release wave 2
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 19.5? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Localization updates
C O UN T RY F EAT URE DESC RIP T IO N

Norway Updated SAF-T export Fixed issue with exporting bank data in
SAF-T in accordance with
BankAccountStructure

India Preview Posting on Service Transfer Document Service Transfer Order in


Order the Indian localization now has Preview
Posting action to enable review of the
different types of entries that will be
created when you post the document.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2021 release wave 2 (release from October 2021 through March 2022), find the link to the release plan
here.

Upgrade to 19.5
Please note that new customers will automatically get the latest builds of Business Central (19.5). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Discover the features for 2022 release wave 1
Discover what's new and planned for Dynamics 365 Business Central 2022 release wave 1. You can find the list
of features here: aka.ms/BCReleasePlan.
Avoid an unexpected data upgrade during cloud migration
When you run cloud migration from a previous version of Business Central, one of the process steps is to run
the data upgrade logic to align the migrated data to the format of the current version. We strongly recommend
that you perform this step one time after you have completed the migration of all your customer’s data to the
online environment. If a planned Business Central major or minor update is applied to this environment, the
update will automatically include the upgrade of the data that was migrated by the cloud migration. These
planned updates also turn off cloud migration for the environment. To avoid this situation, and to allow you to
complete the migration and data upgrade for your environment, we recommend that you postpone any
scheduled major and minor updates for the target environment until you have completed cloud migration. You
can postpone updates in the Business Central admin center. For more information, see Managing Updates.
Upcoming Business Central Office Hours Calls
Make sure to join the office hours call 'Business Central apps in AppSource' on March 8. The call is at 5.00pm -
6.00pm CET / 08.00am -09.00am PST. Register and stay tuned for upcoming calls: aka.ms/BCOfficeHours. Watch
on-demand recordings: aka.ms/BCOfficeHoursRecordings.
Action needed: Client secret-based ser vice to ser vice authentication deprecation for Microsoft
hosted tenants integrating to Dataverse
To ensure no disruptions in integration between Business Central and Dataverse you must upgrade your
Business Central connection to Dataverse to certificate-based authentication.
The change will happen in March 2022. We strongly recommend you perform steps outlined in Upgrade
Connections from Business Central Online to Use Certificate-Based Authentication as soon as possible.
Join Directions NA on April 3-6, 2022
Directions North America is a Microsoft Dynamics 365 event driven by Partners – for Partners. Attendees will
build new business contacts, learn about best practices, and discover valuable tools for execution and success.
Attendees can also use the many networking opportunities at the conference to grow and enhance relationships
with other partners, ISVs, service providers, and Microsoft. Learn more and register here.
Update 19.4 for Microsoft Dynamics 365 Business
Central online 2021 release wave 2
2/6/2023 • 4 minutes to read • Edit Online

Would you like to know what has changed in update 19.4? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Allow Delegated Admin to setup and run Cloud Migration with approval from a licensed user

Localization updates
C O UN T RY F EAT URE DESC RIP T IO N

Mexico CFDI Cancellation Schema changes As of 2022, it will be necessary to


indicate the reason for the cancellation
of the vouchers. We have added the
list of reasons that can be selected for
the posted document before
cancellation

Norway February update for the Electronic VAT Various changes made for the existing
return submission feature Norwegian feature have been made:
Fix issue with opening service
connections when Electronic VAT Setup
does not exist, Fix issue with validating
the sign of VAT Statement Report Line
when VAT Code has "SAF-T VAT Code"
specified, Add missed VAT code “1T”,
and Add possibility to copy reporting
codes to SAF-T codes

Germany Improvement of the visibility of the We have added a possibility to see the
Elster xml file’s content amounts from the resulted Elster xml
file

Italy Intrastat changes Two new fields have been added to the
Intrastat export: Nature of transaction
and Country of origin. Section 5 “call-
of-stock” is not supported in Business
Central, however in the export file an
extra line has been added to Section 5
with all fields blank, for the reason of
keeping the fixed length structure of
the file format.
Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2021 release wave 1 (release from April 2021 through September 2021), find the link to the release plan
here.

Upgrade to 19.4
Please note that new customers will automatically get the latest builds of Business Central (19.4). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Discover the features for 2022 release wave 1
Discover what's new and planned for Dynamics 365 Business Central 2022 release wave 1. You can find the list
of features here: aka.ms/BCReleasePlan.
o Use secondar y read-only database for Power BI repor ting
Please note that with newest Power BI Desktop update (expected in late February 2022) all new Business Central
Power BI reports will be now sourced from a secondary, read-only database. This leaves the main database
ready for transactions, which enhances performance of the system. This feature is part of the Power BI connector
for Business Central. After updating Power BI Desktop this feature it's enabled by default for all new reports but
turned off for existing reports. Read more here.
Avoid an unexpected data upgrade during cloud migration
When you run cloud migration from a previous version of Business Central, one of the process steps is to run
the data upgrade logic to align the migrated data to the format of the current version. We strongly recommend
that you perform this step one time after you have completed the migration of all your customer’s data to the
online environment. If a planned Business Central major or minor update is applied to this environment, the
update will automatically include the upgrade of the data that was migrated by the cloud migration. These
planned updates also turn off cloud migration for the environment. To avoid this situation, and to allow you to
complete the migration and data upgrade for your environment, we recommend that you postpone any
scheduled major and minor updates for the target environment until you have completed cloud migration. You
can postpone updates in the Business Central admin center. For more information, see Managing Updates.
Upcoming Business Central Office Hours Calls
Make sure to join the office hours call 'How to use OAuth, when calling Business Central APIs and web services'
on February 22. The call is at 5.00pm - 6.00pm CET / 08.00am -09.00am PST. Register and stay tuned for
upcoming calls: https://aka.ms/BCOfficeHours. Watch on-demand recordings:
https://aka.ms/BCOfficeHoursRecordings.
Action needed: Client secret-based ser vice to ser vice authentication deprecation for Microsoft
hosted tenants integrating to Dataverse
To ensure no disruptions in integration between Business Central and Dataverse you must upgrade your
Business Central connection to Dataverse to certificate-based authentication.
Although change will happen in March 2022, we strongly recommend you perform steps outlined in Upgrade
Connections from Business Central Online to Use Certificate-Based Authentication as soon as possible.
Join Directions NA on April 3-6, 2022
Directions North America is a Microsoft Dynamics 365 event driven by Partners – for Partners. Attendees will
build new business contacts, learn about best practices, and discover valuable tools for execution and success.
Attendees can also use the many networking opportunities at the conference to grow and enhance relationships
with other partners, ISVs, service providers, and Microsoft. Learn more and register here.
Update 19.3 for Microsoft Dynamics 365 Business
Central online 2021 release wave 2
2/6/2023 • 3 minutes to read • Edit Online

Would you like to know what has changed in update 19.3? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Localization updates
C O UN T RY F EAT URE C H A N GE

EU countries Updates have been made to Intrastat reporting to support


the new requirements for 2022 in each country required to
do Intrastat reporting. These updates are related to the
obligation to report new data -Partner VAT no. and Country
of Origin - for some Intrastat related transactions. The fields
are exported according to the required file format specified
in each country. Additionally, some adjustments in the
Nature of Transaction data field and minor bug fixes are
released. Please find the documentation about Intrastat
reporting here

Mexico Complement to CFDI “Carta de Porte” 2.0. Mexican


companies must be able to print and send Carta de Porte-
compliant packing slips and transfer orders electronically as
Comprobante Fiscal Digital por Internet (CFDI) files. As of
January 1, 2022, the Waybill (Carta de Porte) complement is
mandatory for taxpayers who transport goods and
merchandise in the national territory. Business Central
supports CFDI and Carta de Porte so that you can print
packing slips and transfer orders that have the required
digital signature.

Germany The ASCII file format for Intrastat reporting is no longer


used, therefore ASCII file format has been deprecated in this
release, XML format will be used going forward.

Norway The Electronic VAT return feature has been updated to


support the new requirement for VAT return reporting.

Thefollowing list provides more information about the new electronic VAT return capabilities in Norway:
Possibility to set up VAT Code in the VAT statement
New VAT codes which can be setup from the wizard
New entities related to the new VAT codes introduced:
VAT specification
VAT Note
You can now store and download multiple submission and response requests
The electronic VAT return only supports numbers. Any VAT registration no. with characters will be
converted into numbers only. A VAT registration no. such as NO 777777 MVA will be reported as 777777.
So you won't need to change the existing VAT registration no. in order to do reporting.
Learn more about Norwegian VAT reporting here.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2021 release wave 1 (release from April 2021 through September 2021), find the link to the release plan
here.

Upgrade to 19.3
Please note that new customers will automatically get the latest builds of Business Central (19.3). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Upcoming Business Central Office Hours Calls
Make sure to join the office hours call 'How we secure your data in Business Central' on February 1. Note that
this call will be held in two different time zones; first call is at 08.00am-09.00am CET / 06.00pm-07.00 PM AEST
and second call is at 5.00pm-6.00pm CET / 08.00am-09.00am PST. Register and stay tuned for upcoming calls:
https://aka.ms/BCOfficeHours. Watch on-demand recordings: https://aka.ms/BCOfficeHoursRecordings.
Action needed: Client secret-based ser vice to ser vice authentication deprecation for Microsoft
hosted tenants integrating to Dataverse
To ensure no disruptions in integration between Business Central and Dataverse you must upgrade your
Business Central connection to Dataverse to certificate-based authentication. Although change will happen in
March 2022, we strongly recommend you perform steps outlined in Upgrade Connections from Business
Central Online to Use Certificate-Based Authentication as soon as possible.
Join Directions NA on April 3-6, 2022
Directions North America is a Microsoft Dynamics 365 event driven by Partners – for Partners. Attendees will
build new business contacts, learn about best practices, and discover valuable tools for execution and success.
Attendees can also use the many networking opportunities at the conference to grow and enhance relationships
with other partners, ISVs, service providers, and Microsoft. Learn more and register here.
Update 19.2 for Microsoft Dynamics 365 Business
Central online 2021 release wave 2
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 19.2? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article

Feature changes
Use two-dimensional barcodes in reports (Business Central online)
AL compiler diagnostic messages includes URLs
Synchronize multiline text fields between Business Central and Dataverse (and Dynamics 365 Sales)

Localization updates
All countries that use the Intrastat format have been updated to 2022 requirements
MX Carta de Porte 2.0
New VAT Return submission for Norway

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2021 release wave 1 (release from April 2021 through September 2021), find the link to the release plan
here.

Upgrade to 19.2
Please note that new customers will automatically get the latest builds of Business Central (19.2). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Upcoming Business Central Office Hours Calls
Make sure to join the office hours calls 'Universal Code Initiative' on January 11 and 'How we secure your data
in Business Central' on February 1. Note that these calls will be held in two different time zones; first call is at
08.00am-09.00am CET / 06.00pm-07.00 PM AEST and second call is at 5.00pm-6.00pm CET / 08.00am-09.00am
PST. Register and stay tuned for upcoming calls: https://aka.ms/BCOfficeHours. Watch on-demand recordings:
https://aka.ms/BCOfficeHoursRecordings.
Action needed: Client secret-based ser vice to ser vice authentication deprecation for Microsoft
hosted tenants integrating to Dataverse
To ensure no disruptions in integration between Business Central and Dataverse you must upgrade your
Business Central connection to Dataverse to certificate-based authentication. Although change will happen in
March 2022, we strongly recommend you perform steps outlined in Upgrade Connections from Business
Central Online to Use Certificate-Based Authentication as soon as possible.
Business Central Launch Event
On October 18, we released the Business Central Launch Event - an online event with 15 sessions on what's new
in Dynamics 365 Business Central 2021 release wave 2. The sessions are within the following four areas:
Administration and Development, Service and Platform, Better with Microsoft 365 and Modern Client. Register
and watch the 15 sessions now: aka.ms/BCLE.
Apps in AppSource
We now have 2000+ Business Central apps in AppSource! Find all the apps here: Business Central apps in
AppSource.
Update 19.1 for Microsoft Dynamics 365 Business
Central online 2021 release wave 2
2/6/2023 • 4 minutes to read • Edit Online

Would you like to know what has changed in update 19.1? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

IMPORTANT
Builds for Business Central in Ukraine are now released.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Copying environments of different types
Operations log enhancements
Restart environments
Support for 2D barcodes
Shipping agent information is copied from sales orders to warehouse shipments

Localization updates
C O UN T RY F EAT URE C H A N GE DO W N LO A D L IN K

Mexico Complement to CFDI “Carta de Porte” Version 2017, Version 2018, Spring
1.0. Mexican companies must be able 2019, 2020 Release Wave 2, 2021
to print and send Carta de Porte- Release Wave 1, 2021 Release Wave 2
compliant packing slips and transfer
orders electronically as Comprobante
Fiscal Digital por Internet (CFDI) files.
As of December 1, 2021, the Waybill
(Carta de Porte) complement is
mandatory for taxpayers who
transport goods and merchandise in
the national territory. Business Central
supports CFDI and Carta de Porte so
that you can print packing slips and
transfer orders that have the required
digital signature.
C O UN T RY F EAT URE C H A N GE DO W N LO A D L IN K

United States Form 1099. Format changes as of


December 2021: The Internal Revenue
Service (IRS) requires one or more
versions of the 1099 tax form for
payments to vendors. Copies of these
forms must be sent to vendors
annually on or before the last day of
January. On your purchase documents,
you can specify that the document is
1099 liable, and you can specify the
1099 code for the vendor. Reporting
Transactions as 1099 Liable in the US.

Business Central is released in the following new countries:


Argentina
Bulgaria
Chile
Puerto Rico
Slovakia
Ukraine

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2021 release wave 1 (release from April 2021 through September 2021), find the link to the release plan
here.

Upgrade to 19.1
Please note that new customers will automatically get the latest builds of Business Central (19.1). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Business Central Office Hours Calls in November
Make sure to watch the office hours call recording on 'Improvements to data synchronization to Dataverse and
Dynamics 365 Sales' from November 9 and join 'Can Business Central Online (SaaS) handle large customers?'
on November 30. Register and stay tuned for the upcoming calls: https://aka.ms/BCOfficeHours. Watch on-
demand recordings: https://aka.ms/BCOfficeHoursRecordings.
Action needed: Client secret-based ser vice to ser vice authentication deprecation for Microsoft
hosted tenants integrating to Dataverse
To ensure no disruptions in integration between Business Central and Dataverse you must upgrade your
Business Central connection to Dataverse to certificate-based authentication. Although change will happen in
March 2022, we strongly recommend you perform steps outlined in Upgrade Connections from Business
Central Online to Use Certificate-Based Authentication as soon as possible.
Business Central Launch Event
On October 18, we released the Business Central Launch Event - an online event with 15 sessions on what's new
in Dynamics 365 Business Central 2021 release wave 2. The sessions are within the following four areas:
Administration and Development, Service and Platform, Better with Microsoft 365 and Modern Client. Register
and watch the 15 sessions now: aka.ms/BCLE.
Find Records action in Power Automate Business Central connector
Coming to you in the coming weeks together with a cloud-based update of Business Central online connector
for Power Automate is a new action allowing to find records based on a value (or any supported OData filter –
more here). This will allow you to create both instant or flows in Power Automate that get a value from the user
or any system in a form of automation, then find data in Business Central and then process data in business
Central. An example of such scenario was shown ad Directions EMEA 2021 in Milan in a form of chatbot hosted
inside Microsoft Teams and built using Power Virtual Agents – that chatbot took an input from the user, found an
item in Business Central and came back with inventory data.
Customer References
We now have 100+ Business Central customer stories on the Microsoft Customer Stories site. These stories
come in handy when prospects ask for reference stories, so remember to bookmark: Microsoft Customer Stories
Search.
AL Compiler Diagnostics
With the latest documentation refresh, the AL compiler diagnostics are published in preview. The AL diagnostics
section lists all of the compiler errors, warnings, etc. that you can get when coding and compiling in AL. The
topics are auto-generated and there is one topic per diagnostic rule, which allows for adding detailed help, hints,
reference, and more. At this point, the topics contain only the error message, and adding more information is
going to be a work in progress. To contribute with content, see instructions in AL Diagnostics.
Update 18.5 for Microsoft Dynamics 365 Business
Central online 2021 release wave 1
2/6/2023 • 3 minutes to read • Edit Online

Would you like to know what has changed in update 18.5? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

IMPORTANT
Builds for Business Central in Türkiye are now live.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Extension validation on upgrade

Localization updates
C O UN T RY F EAT URE C H A N GE

Mexico Retention functionality for copied documents when


cancelling or creating corrective Sales Credit Memos

Italy Tax Authority Doc. No. enlarged

Switzerland Support for multiple QR-IBAN bank accounts for issuers of


QR-Bills

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2021 release wave 1 (release from April 2021 through September 2021), find the link to the release plan
here.

Upgrade to 18.5
Please note that new customers will automatically get the latest builds of Business Central (18.4). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Business Central Office Hours Calls in September
Make sure to join the office hours call around 'How to use OAuth, when calling Business Central APIs and web
services' on September 14. Register and stay tuned for the upcoming calls: https://aka.ms/BCOfficeHours.
Action needed: Client secret-based ser vice to ser vice authentication deprecation for Microsoft
hosted tenants integrating to Dataverse
To ensure no disruptions in integration between Business Central and Dataverse you must upgrade your
Business Central connection to Dataverse to certificate-based authentication. Although change will happen in
March 2022, we strongly recommend you perform steps outlined in Upgrade Connections from Business
Central Online to Use Certificate-Based Authentication as soon as possible.
Join Directions EMEA
Directions EMEA is your opportunity to network with other partners in the Dynamics 365 Business Central
community, as well as to attend in-depth application, technical, sales & marketing, and executive sessions about
Business Central, alongside sessions around Power Platform and Dynamics 365 workloads. Microsoft is sending
50+ staff members to cover all areas of Business Central from product development and support to product
overview and future vision. There will be hands-on labs, round tables, and over 100 sessions that will dive into
all areas of the product to help partners be more successful. Microsoft will host keynotes, addressing what’s new
with Business Central, as well as future roadmap.
Conference details:
October 27-29 in Milan
MiCo Milano Convention Center, Piazzale Carlo Magno, 1 – 20149, Milan
Event website: https://directions4partners.com/events/directions-emea/
Customer Consent capabilities for all features that exchange data with 3rd par ty ser vices
Business Central capabilities enable companies to seamlessly integrate with other parties needed to achieve
business goals or statutory obligations.
In the Setup pages for each feature interchanging data from Business Central to another service, the user will
see a text informing that the affected Business Central data might be shared with third party systems and
flowing outside of the organization’s selected geographic boundaries with an option to enable/disable the
feature and therefore get even better control of the data share.

NOTE
If a feature is already made available and used, to avoid disruptions of ongoing business processes, it will remain available
until the administrator takes action to turn it off.

Features in scope:
AMC Banking Fundamentals
EU VAT Reg. No. Validation Service
OCR Services
PayPal Payments Standard
Electronic Invoicing - Tradeshift
Envestnet Yodlee Bank Feeds Service
United Kingdom: Making Tax Digital for VAT Capabilities in Dynamics 365 Business Central
Spain: SII - Invoice and Credit Memo Types in Sales and Purchase Documents
Czech Republic: Core Localization Pack for Czech
Registration number verification
Electronic registration of sales
Currency Exchange Rate
VAT unreliable payer check
Update 18.4 for Microsoft Dynamics 365 Business
Central online 2021 release wave 1
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 18.4? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Localization updates
C O UN T RY F EAT URE C H A N GE

Great Britain Specify fraud prevention headers automatically without


interaction with the user

Norway SAF-T Improvements

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2021 release wave 1 (release from April 2021 through September 2021), find the link to the release plan
here.

Upgrade to 18.4
Please note that new customers will automatically get the latest builds of Business Central (18.4). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Business Central Office Hours Calls in August
Make sure to join the office hours call around 'Cloud Migration' on August 31. Register and stay tuned for the
upcoming calls: https://aka.ms/BCOfficeHours.
Action needed: Client secret-based ser vice to ser vice authentication deprecation for Microsoft
hosted tenants integrating to Dataverse
To ensure no disruptions in integration between Business Central and Dataverse you must upgrade your
Business Central connection to Dataverse to certificate-based authentication. Although change will happen in
March 2022, we strongly recommend you perform steps outlined in Upgrade Connections from Business
Central Online to Use Certificate-Based Authentication as soon as possible.
Users see notification when they open the obsolete repor ts 204, 205, 206, & 207
Before 2021 release wave 1, we announced that we were planning to replace several reports with newer
versions. As the time approaches for the final clean-up, we start displaying notifications so that the affected
users can take action before Business Central 2021 release wave 2.
If you still use one or more of the deprecated reports, now is the time to start using the recommended reports,
alternatively you can clone the deprecated reports to a custom range, and switch to the cloned reports.
To check if your company uses old reports, search for Repor t Selection – Sales , and check which reports are
configured to be used for Quote, Order, Quote, and Credit Memo. Remember to inspect the content of the
Custom Repor t Selection table (object ID 9657), to detect if these reports are used for specific customers. For
more information, see: View a table object directly from the client. Once you know which customers use these
reports, you can replace them on the Document Layout page for each affected customer, or you can use
configuration packages to update in bulk.
Update 18.3 for Microsoft Dynamics 365 Business
Central online 2021 release wave 1
2/6/2023 • 3 minutes to read • Edit Online

Would you like to know what has changed in update 18.3? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Feature changes
Service-to-service authentication
Dimension issues detection and repair tool
Integration of Word templates
Data administration and cleanup tasks page
Integration of Word templates with interaction templates
Export any list part to Excel
New countries added to the list of supported countries
Business Central Database capacity changes (as of July 1, 2021)
Upgrade to certificate-based Service-to-service (S2S) authentication for Dataverse and Dynamics 365
Integration
Get report (raw data) into Excel from request page (targeting end users) and Save report dataset to excel
from the request page (targeting developers)

Hotfixes
Find an overview of hotfixes in this article.

Localization updates
C O UN T RY F EAT URE C H A N GE

W1 Enhance the Update Document page for posted documents


(support for Payment Reference and Payment Method)

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2021 release wave 1 (release from April 2021 through September 2021), find the link to the release plan
here.

Upgrade to 18.3
Please note that new customers will automatically get the latest builds of Business Central (18.3). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Expor t any List to Excel
In this version an “Open in Excel” action has been added to list parts under the Manage group in action bar. This
is only present if the user or admin enabled the feature via Feature Management, so please make sure you do
that. Read more here.
Two new sessions added to the collection of Business Central Launch Event 2021r w1 recordings
We've added two new sessions to the collection of Business Central Launch Event recordings. The two sessions
are on 'Docker' and 'DevOps Processes for Per Tenant Extensions' with Freddy Kristiansen as the speaker on
both sessions. They can be found here.
Go Local: New Azure data center regions for Switzerland and Nor way
With the Business Central online service, we strive to provide the best experience and performance for our
customers. Therefore, we're moving the environments running on the Swiss version of Business Central to the
Switzerland North Azure region and the environments running on the Norwegian version of Business Central to
the Norway East Azure region. With 2021 release wave 1 minor update 18.3, all newly created Business Central
online environments will be created in the local Azure regions and we will start moving existing customers in
the weeks after release of minor update 18.3. Learn more about supported countries and Azure regions here.
Users see notification when they open the obsolete repor ts 204, 205, 206, & 207
Before 2021 release wave 1, we announced that we were planning to replace several reports with newer
versions. As the time approaches for the final cleaning up, we start displaying notifications so that the affected
users can take action before 2021 release wave 2.
If you still use one or more of the deprecated reports, now is the time to start using the recommended reports,
alternatively you can clone the deprecated reports to a custom range, and switch to the cloned reports.
To check if your company uses old reports, search for Repor t Selection – Sales , and check which reports are
configured to be used for Quote, Order, Quote, and Credit Memo. Remember to inspect the content of the
Custom Repor t Selection table (object ID 9657), to detect if these reports are used for specific customers. For
more information, see: View a table object directly from the client. Once you know which customers use these
reports, you can replace them on the Document Layout page for each affected customer, or you can use
configuration packages to update in bulk.
Action needed: Client secret-based ser vice to ser vice authentication deprecation for Microsoft
hosted tenants integrating to Dataverse
To ensure no disruptions in integration between Business Central and Dataverse you must upgrade your
Business Central connection to Dataverse to certificate-based authentication. Although change will happen in
March 2022, we strongly recommend you perform steps outlined in Upgrade Connections from Business
Central Online to Use Certificate-Based Authentication as soon as possible.
Update 18.2 for Microsoft Dynamics 365 Business
Central online 2021 release wave 1
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 18.2? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

IMPORTANT
Business Central online version 18.2 for India is now available. For more information, see Update 18.2 for Microsoft
Dynamics 365 Business Central 2021 Release Wave 1.

Hotfixes
Find an overview of hotfixes in this article.

Localization updates
C O UN T RY F EAT URE C H A N GE

United Kingdom Configurable fraud prevention headers in making tax digital

Spain Improve multiple SII special sheme codes functionality

W1 Configurable Instrastat checklist setup

Italy Update for Certificazione Unica

Spain Support VAT cash refunds in the SII functionality

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2021 release wave 1 (release from April 2021 through September 2021), find the link to the release plan
here.

Upgrade to 18.2
Please note that new customers will automatically get the latest builds of Business Central (18.2). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Available for all countries: Schedule minor updates and receive email notifications
All customers can now receive up-front email notifications seven days in advance and schedule minor updates
of Business Central within 21 days. We enabled this capability for US with 18.1, and are now enabling the same
experience for all other countries with 18.2. Learn more: https://aka.ms/BCUpdates.
New ways of working with Business Central data in Power BI
In the upcoming June update to Power BI Desktop we have included a new connector for Business Central
allowing you to get data faster from Business Central to Power BI. Note the update to Power BI Desktop is
scheduled later in June and you will get it automatically if you have installed Power BI Desktop from Microsoft
Store. Read more about the new capabilities here. Please note that this change is for Business Central online
only.
AboutTitle and AboutText proper ties
We’ve updated AL reference docs with plenty of details, including the list of page combinations where the About
properties have different or no effect. Update 18.2 fully reflects these behaviours.
Business Central Office Hours Calls in June
Make sure to join the office hours calls around 'Working with Dimensions' on June 15 and 'DevOps for Per
Tenant Extensions' on June 29. Register and stay tuned for the upcoming calls: https://aka.ms/BCOfficeHours.
Also, notice that in the month of July, there will be no office hours calls.
Suppor t for migrating data from earlier on-premises versions of Business Central to 2021 release
wave 1 (v.18)
With the Business Central cloud migration tool, customers can migrate their data from earlier on-premises
versions of the product to their online Business Central environment, running on the latest version. We've added
support for customers who are running on Business Central on-premises version 14, 15, 16, or 17 to migrate
their data to version 18 of Business Central online. We've implemented the necessary data upgrade logic in the
cloud migration tool, so customers don't have to upgrade their older version themselves in order to migrate
their data to the latest online release.
Update 18.1 for Microsoft Dynamics 365 Business
Central online 2021 release wave 1
2/6/2023 • 3 minutes to read • Edit Online

Would you like to know what has changed in update 18.1? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

IMPORTANT
Builds for Business Central version 18.1 on-premise are now available. For more information, see Update 18.1 for
Microsoft Dynamics 365 Business Central 2021 Release Wave 1.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Editing in Excel more reliably
Support authentication of a SMTP connection using OAuth2
Extension lifecycle telemetry include signal from dependent extensions
Edit active prices in Prices Overview and implement price changes using Price Worksheet
Send documents as emails with any attached files automatically added as email attachments

Localization updates
C O UN T RY F EAT URE C H A N GE

Canada and US Updates for Include Tax with partial shipping and
prepayment credit memo

Italy Changes in withholding tax declaration 2021

Italy Updated for E-invoicing functionality

Belgium Update for File Domiciliation in SEPA Direct Debit export

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2021 release wave 1 (release from April 2021 through September 2021), find the link to the release plan
here.

Upgrade to 18.1
Please note that new customers will automatically get the latest builds of Business Central (18.1). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Suppor t for migrating data from earlier on-premises versions of Business Central to 2021 release
wave 1 (v.18)
With the Business Central cloud migration tool, customers can migrate their data from earlier on-premises
versions of the product to their online Business Central environment, running on the latest version. We've added
support for customers who are running on Business Central on-premises version 14, 15, 16, or 17 to migrate
their data to version 18 of Business Central online. We've implemented the necessary data upgrade logic in the
cloud migration tool, so customers don't have to upgrade their older version themselves in order to migrate
their data to the latest online release.
US customers: Schedule minor updates and receive email notifications
US customers can now receive up-front email notifications seven days in advance and schedule minor updates
of Business Central within 21 days. We have enabled this new capability to be available for US with 18.1, and
plan to enable the same experience for all other countries with 18.2. Stay tuned for updates! Learn more:
https://aka.ms/BCUpdates.
Business Central Office Hours Calls in May
Make sure to join the office hours calls around ‘Report Extensibility’ on May 4 and ‘Snapshot debugging’ on
May 18. Register and stay tuned for the upcoming calls: https://aka.ms/BCOfficeHours.
Business Central Launch Event
You can still watch the 15+ on-demand sessions from the Business Central Launch Event. The sessions revolve
around the new Dynamics 365 Business Central features and capabilities — everything from working with
dimensions, permissions and entitlements, to product announcements and onboarding customers. Register for
free: aka.ms/BCLE.
Updated versions of the Business Central mobile apps are being released to all three stores this
month (covering some fixes and improvements):
Fixed a problem where the Windows UWP desktop/tablet app was sometimes displaying blank screen on
restart
Fixed a problem when iOS mobile app running on-premises in certain conditions required the user to enter
credentials with every login
Fixed a problem with iOS mobile app related to failed download when previewing a report
Fixed a problem with Android mobile app not being able to install on devices where a GPS module was
disabled or missing
Fixed connectivity problems with Business Central cloud
Please download and always use the latest version: Windows (Microsoft Store), iOS (Apple's App Store) or
Android (Google's Play Store). Currently recommended versions of these apps are 3.2.x and 3.3.x (or later).
Update 17.5 for Microsoft Dynamics 365 Business
Central online 2020 release wave 2
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 17.5? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Localization updates
C O UN T RY F EAT URE C H A N GE

Netherlands Intrastat support for Partner VAT ID and Country of Origin

Spain Support for using Sales Invoice as substitution type in


Immediate Supply of Information (SII)

Spain Support for delivery of goods and services in the same


foreign customer document in Immediate Supply of
Information (SII)

Germany Support of two new ciphers in preliminary VAT


Return/Advance notification (kz37 and kz50)

Belgium New field to control inclusion of a customer on the VAT


Annual Listing

Norway SAF-T update: Improved data export for Contact and Post
Code information

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2020 release wave 2 (release from October 2020 through March 2021), find the link to the release plan
here.

Upgrade to 17.5
Please note that new customers will automatically get the latest builds of Business Central (17.5). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Business Central Office Hours Calls in March
Make sure to join the office hours calls around ‘Integrating with Teams’ on March 9 and ‘Business Central apps
in AppSource’ on March 23. Register and stay tuned for the upcoming calls: https://aka.ms/BCOfficeHours.
OData V3 will be removed with 2021 Wave 1
As previously announced, OData Version 3.0 (V3) has been deprecated since April 2020 and support for it will
be removed in Dynamics 365 Business Central 2021 release wave 1. OData V4 is the current recommended
version of OData and current integrations needs to move to OData V4. To identify incoming OData V3 requests,
enable and use the Web Service Request telemetry that's available to partners. Notifications has also been sent
via M365 Message Center to tenants with identified usage.
Basic Authentication
Basic Authentication (Web Service Access Key) removal for Business Central online has been postponed until
April 2022. We see that some integrations needs more time to move from Web Service Access Key usage to
OAuth. PowerShell samples on how to connect to Business Central is published on GitHub.
It’s time to switch your Dynamics 365 Business Central browser to Microsoft Edge
On April 2, 2021, Microsoft will remove Internet Explorer 11 and Microsoft Edge Legacy browsers from the list
of supported browsers for the Business Central modern clients. Read the details, how it applies to you and
actions to take here.
Update 17.4 for Microsoft Dynamics 365 Business
Central online 2020 release wave 2
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 17.4? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Use recurring journals to allocate balances by dimension values
The Busines Central app for Microsoft Teams reaches General Availability

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2020 release wave 2 (release from October 2020 through March 2021), find the link to the release plan
here.

Upgrade to 17.4
Please note that new customers will automatically get the latest builds of Business Central (17.4). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
OData V3 will be removed with 2021 Wave 1
As previously announced, OData Version 3.0 (V3) has been deprecated since April 2020 and support for it will
be removed in Dynamics 365 Business Central 2021 release wave 1. OData V4 is the current recommended
version of OData and current integrations needs to move to OData V4. To identify incoming OData V3 requests,
enable and use the Web Service Request telemetry that's available to partners. Notifications has also been sent
via M365 Message Center to tenants with identified usage.
Release Plan for wave 1 2021 is out
The release plan for Dynamics 365 Busines Central wave 1 2021 is now live! You can find an overview of all the
new and planned features here.
Basic Authentication
Basic Authentication (Web Service Access Key) removal for Business Central online has been postponed until
April 2022. We see that some integrations needs more time to move from Web Service Access Key usage to
OAuth. PowerShell samples on how to connect to Business Central is published on GitHub.
Business Central Office Hours Calls in Februar y
Make sure to join the office hours calls around ‘Power Platform Integration, Power Apps, and Dataverse’ on
February 9 and ‘Performance Toolkit and Telemetry; How to deploy for performance’ on February 23. Register
and stay tuned for the upcoming calls: https://aka.ms/BCOfficeHours.
It’s time to switch your Dynamics 365 Business Central browser to Microsoft Edge
On April 2, 2021, Microsoft will remove Internet Explorer 11 and Microsoft Edge Legacy browsers from the list
of supported browsers for the Business Central modern clients. Read the details, how it applies to you and
actions to take here.
Update 17.3 for Microsoft Dynamics 365 Business
Central online 2020 release wave 2
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 17.3? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Restoring an Environment in the Admin Center
Use Shortcut dimensions in G/L Entries for Financial reporting
Signal from web service key authentication added to Application Insights telemetry for partners
Handle Price List Exceptions with Allow Updating Defaults

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2020 release wave 2 (release from October 2020 through March 2021), find the link to the release plan
here.

Upgrade to 17.3
Please note that new customers will automatically get the latest builds of Business Central (17.3). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Basic Authentication
Basic Authentication (Web Service Access Key) removal for Business Central online has been postponed until
April 2022. We see that some integrations needs more time to move from Web Service Access Key usage to
OAuth. PowerShell samples on how to connect to Business Central is published on GitHub.
Snapshot debugging is now enabled in production environments
From version 17.2 and forward it is now possible to use snapshot debugging to investigate production
environments. For more information, see the help page or view the Virtual Event for 2020 Wave 2 release
recording on the What's New in Visual Studio and AL, covering snapshot debugging in details.
Business Central Office Hours Calls in Januar y
Make sure to join the office hours calls around 'Customer Migration Tooling' on January 12 and 'Power Platform
Integration – Power BI' on January 26. Register and stay tuned for the upcoming calls:
https://aka.ms/BCOfficeHours.
Want to improve the performance of Business Central?
Visit https://aka.ms/bcperformance and learn about best practices, dos and don'ts and different ways to make
changes with a performance impact. The Performance Tuning Guide will help you understand and improve the
performance of Business Central whether you are a functional consultant, a developer, or an administrator.
It's time to switch your Dynamics 365 Business Central browser to Microsoft Edge
On April 2, 2021, Microsoft will remove Internet Explorer 11 and Microsoft Edge Legacy browsers from the list
of supported browsers for the Business Central modern clients. Read the details, how it applies to you and
actions to take here.
Update 17.2 for Microsoft Dynamics 365 Business
Central online 2020 release wave 2
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 17.2? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Application Performance Improvements
Signal from job queue execution added to Application Insights telemetry for partners
Signal from permission changes to added to Application Insights telemetry for partners
Signal from the retention policy feature added to Application Insights telemetry for partners
Signal from the sensitive field audit feature added to Application Insights telemetry for partners
Signal from the email feature added to Application Insights telemetry for partners
Signal from application packages lifecycle added to Application Insights Telemetry for partners
Snapshot Debugging

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2020 release wave 2 (release from October 2020 through March 2021), find the link to the release plan
here.

Upgrade to 17.2
Please note that new customers will automatically get the latest builds of Business Central (17.2). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Business Central Office Hours
The Office Hours are back! Find an overview of the topics and register here: https://aka.ms/BCOfficeHours.
Small update for Business Central mobile app
A small update for the Business Central mobile app (with added languages and some fixes) is being released to
the app stores on all three platforms (Windows, iOS, and Android). Please remember to update the Business
central app on your device (version 3.1.12032 or later). Direct links: Windows (Microsoft Store), iOS (Apple's App
Store), Android (Google's Play Store).
Watch what's new sessions on demand
You can still watch the sessions from the Business Central Launch Event in October. Register and get access to
30+ sessions here.
Migrate directly from version 14, 15, and 16 to Business Central online
Business Central includes a cloud migration tool that administrators can use to migrate customer data from on-
premises databases to Business Central online. Starting now, the Cloud Migration app also supports migration
from the earlier on-premises versions of Business Central, with the latest cumulative update applied: Migrate
directly from versions 14.x, 15.x, and 16.x to version 17.x. This helps customers reduce their costs of migrating to
the Business Central cloud significantly, as they can skip upgrading their on-premises environments to the latest
version of Business Central and just migrate the data, including all historical transactions. The Cloud Migration
app now includes all the necessary data upgrade logic to convert the data from the previous versions to the
data structure of 2020 release wave 2 (version 17.0). Learn more here.
Update 17.1 for Microsoft Dynamics 365 Business
Central online 2020 release wave 2
2/6/2023 • 3 minutes to read • Edit Online

Would you like to know what has changed in update 17.1? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Enhanced email capabilities
Notify users of high-risk changes in selected setup fields
Use new sales pricing experience
Control how Account Schedules for core financial reports are generated
Improved VAT Registration no. lookup
Extension lifecycle telemetry in Application Insights for ISVs
Use environmentType and environmentName launch.json properties instead of obsoleted sandboxName
Symbols can be downloaded with a snapshot initialize launch.json configuration, using above environment
properties

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2020 release wave 2 (release from October 2020 through March 2021), find the link to the release plan
here.

Upgrade to 17.1
Please note that new customers will automatically get the latest builds of Business Central (17.1). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
NEW! Migrate directly from version 14, 15, and 16 to Business Central online
Business Central includes a cloud migration tool that administrators can use to migrate customer data from on-
premises databases to Business Central online. Starting now, the Cloud Migration app also supports migration
from the earlier on-premises versions of Business Central, with the latest cumulative update applied: Migrate
directly from versions 14.x, 15.x, and 16.x to version 17.x. This helps customers reduce their costs of migrating to
the Business Central cloud significantly, as they can skip upgrading their on-premises environments to the latest
version of Business Central and just migrate the data, including all historical transactions. The Cloud Migration
app now includes all the necessary data upgrade logic to convert the data from the previous versions to the
data structure of 2020 release wave 2 (version 17.0). Learn more here.
Database size when migrating from Business Central on-prem to online
We have increased the limit we apply to the database size from 30 Gb to 80 Gb when migrating from Business
Central on-prem to Business Central online using the Cloud Migration tool. If you are looking at migrating a
larger database, we recommend that you contact the support team and work with them to make sure that the
migration is successful. Learn more here and read about running the cloud migration tool here.
Watch what's new sessions on demand
Watch the sessions from the Business Central Launch Event in October. Register and get access to 30+ sessions
here.
Snapshot debugging
Snapshot debugging has now been enabled for sandbox environments. It will be enabled in production in a later
minor. Learn more here.
Apps are moving to office.com
The home for all your business applications across Dynamics 365 and Microsoft Power Platform is moving to
office.com, where you'll find the Business Central tiles for production and sandbox environments. Learn more
here.
Easy access to production or sandbox environments from the mobile app
Users of mobile devices can now choose between their sandbox and production environments without the need
to use the pre-crafted URL as before. Partners running their own apps based on Business Central can also let
their users explore it from mobile devices. Learn more here.
Unblock multifactor authentication for mobile apps
We have updated core authentication components of the mobile app to support multifactor authentication.
Enabling such flow in the user setting on your Microsoft 365 account and then using it on a mobile device (via
an SMS code, authenticator app, or more) is now possible after updating the Business Central mobile app to
version 3.0 or higher. Learn more here.
Update 16.5 for Microsoft Dynamics 365 Business
Central online 2020 release wave 1
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 16.5? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Feature changes
Delete extension data

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2020 release wave 1 (release from April 2020 through September 2020), find the link to the release plan
here.
For a list of next wave release plans, see the 2020 release wave 2 release plan.

Upgrade to 16.5
Please note that new customers will automatically get the latest builds of Business Central (16.5). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
It’s time to switch your Dynamics 365 Business Central browser to Microsoft Edge
On April 2, 2021, Microsoft will remove Internet Explorer 11 and Microsoft Edge Legacy browsers from the list
of supported browsers for the Business Central modern clients. Read the details, how it applies to you and
actions to take here.
Leveraging IoT data in Dynamics 365 Business Central
Make sure to read the blog about getting started with leveraging the Internet of Things (IoT) data in Dynamics
365 Business Central using services from Microsoft Azure is easier than you may think.
Suppor t for an unlimited number of production and sandbox environments
With 2020 release wave 2 (October), we're introducing the ability for customers to buy additional Business
Central production environments to expand their business. More environments will open up new opportunities
like creating more business branches, moving into more countries, or expanding within their current country,
read more here.
Running a Container-Based Development Environment
From 16.4 and onwards Microsoft will stop producing docker images and instead publish builds as artifacts,
which can be used together with the generic Docker image to run the image you want. Read more here.
Update 16.4 for Microsoft Dynamics 365 Business
Central online 2020 release wave 1
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 16.4? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links that you might find interesting.

Hotfixes
Find an overview of hotfixes in this article.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2020 release wave 1 (release from April 2020 through September 2020), find the link to the release plan
here.
For a list of next wave release plans, see the 2020 release wave 2 release plan.

Upgrade to 16.4
Please note that new customers will automatically get the latest builds of Business Central (16.4). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Running a Container-Based Development Environment
From 16.4 and onwards Microsoft will stop producing docker images and instead publish builds as artifacts,
which can be used together with the generic Docker image to run the image you want. Read more here.
Want to improve the performance of Business Central?
Visit aka.ms/bcperformance and learn about best practices, dos and don'ts and different ways to make changes
with a performance impact. The Performance Tuning Guide will help you understand and improve the
performance of Business Central whether you are a functional consultant, a developer, or an administrator.
Vir tual sessions of what is new in 2020 release wave 1?
Did you attend the #MSDyn365BCVirtualEvent on June 3rd? Don't forget to watch the 15+ virtual on demand
sessions featuring new innovations, tools, and in-depth product demonstrations from the experts. You just need
to register to view the sessions, but it’s free.
Update 16.3 for Microsoft Dynamics 365 Business
Central online 2020 release wave 1
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 16.3? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update. In addition, we have gathered some
good to know information and links, you might find interesting.

Hotfixes
Link to Hotfixes.

Feature changes
Bank reconciliation improvements
Extension lifecycle telemetry in Application Insights for partners
Client page view telemetry in Application Insights for partners
Installing AppSource apps updates in the Business Central administration center – rollout has been
completed. Customers can now discover and install all AppSource apps updates in the Business Central
Admin Center.
Feature Update: Page layout is now cached to browser storage

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2020 release wave 1 (release from April 2020 through September 2020), find the link to the release plan
here.

Upgrade to 16.3
Please note that new customers will automatically get the latest builds of Business Central (16.3). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Keep track on deployed builds
In between the Microsoft Dynamics 365 Business Central minor updates we deploy new builds as they become
available. Visit the Update History to see the latest important builds that have been pushed out automatically
since last minor update.
Want to improve the performance of Business Central?
Visit aka.ms/bcperformance and learn about best practices, dos and don'ts and different ways to make changes
with a performance impact. The Performance Tuning Guide will help you understand and improve the
performance of Business Central whether you are a functional consultant, a developer, or an administrator.
Are you a Business Central Wave 'Champ'?
Did you attend the #MSDyn365BCVirtualEvent on June 3rd? Don't forget to watch the 15+ virtual on demand
sessions featuring new innovations, tools, and in-depth product demonstrations from the experts. The best part
of it - it's all for free! You just need to register to become a Business Central 'Wave Champ' and boost your
knowledge.
Update 16.2 for Microsoft Dynamics 365 Business
Central online 2020 release wave 1
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 16.2?


Below you'll find an overview and relevant links to what has been done on hotfixes and regulatory features in
this update. In addition, we have gathered some good to know information and links, you might find interesting.

Hotfixes
Link to Hotfixes

Feature changes
Migrate data from Business Central 14.x on-premises to Business Central 15.x online
Update error telemetry in Application Insights for partners
New URL parameter hides web client header
Improved user experience to keep things from going wrong
Use modern authentication to connect to Microsoft Dataverse and Dynamics 365 Sales
Installing AppSource apps updates in the Business Central administration center – please note gradual
availability! Until the feature is generally available, some AppSource apps can't be updated using this feature.
For information about the timeline, see here

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire 2020 release wave 1 (release from April 2020 through September 2020), find the link to the release plan
here.

Upgrade to 16.2
Please note that new customers will automatically get the latest builds of Business Central (16.2). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
A change to the Web client header
The top-most header in the Business Central Web client and desktop app have been updated to align with other
Microsoft 365 and Dynamics 365 apps. The most notable change is to the height of the header that has now
been reduced to 48 pixels.
Warning of performance impact when using configuration packages to impor t data
Configuration packages were designed to speed up the implementation of new companies. In case a customer
wants to use Configuration Packages as a quick way to import data -sometimes big data- from other systems to
Business Central, this small feature analyzes if the import will bring data to a new company or not and,
depending of that and the size of the package, alerts the user that the performance of its tenant could be
affected suggesting other ways to import or request partner help.
Want to improve the performance of Business Central?
Visit aka.ms/bcperformance and learn about best practices, dos and don'ts and different ways to make changes
with a performance impact. The Performance Tuning Guide will help you understand and improve the
performance of Business Central whether you are a functional consultant, a developer, or an administrator.
Are you a Business Central Wave ‘Champ’?
Did you attend the #MSDyn365BCVirtualEvent on June 3rd? Don’t forget to watch the 15+ virtual on demand
sessions featuring new innovations, tools, and in-depth product demonstrations from the experts. The best part
of it - it’s all for free! You just need to register to become a Business Central ‘Wave Champ’ and boost your
knowledge.
Update 16.1 for Microsoft Dynamics 365 Business
Central 2020 online release wave 1
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 16.1?


Below you'll find an overview and relevant links to what has been done on hotfixes and regulatory features in
this update. In addition, we have gathered some good to know information and links, you might find interesting.

Hotfixes
Link to Hotfixes

Feature changes
Company lifecycle telemetry in Application Insights for partners

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire wave 1 (release from April 2020 through September 2020), find the link to the release plan here.

Upgrade to 16.1
Please note that new customers will automatically get the latest builds of Business Central (16.1). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Minimum requirements for Business Central Administration Center
We have updated system requirements with the list of browsers supported by the Administration Center.
When signing in from an unsupported browser that delivers a significantly degraded experience,
administrators will immediately see a message that prevents them from continuing to the Administration
Center. For example, it is not possible to access the Business Central Administration Center from Internet
Explorer.
See minimum requirements
Learn more about the Business Central Administration Center
Sandbox environment picker
When you navigate from the Business Central Sandbox tile in the Dynamics 365 Home portal or in the
App Launcher, a dialog will be displayed for you to choose exactly which sandbox environment from your
organization you would like to navigate to.
Read more about sandbox environments
Message to Global Admins about the capabilities
On login, Global Admins will get a message about the capabilities in Business Central according to their
license or suggesting one if they don't have any assigned.
Coming up: Vir tual par tner readiness event - register now!
We're excited to share the latest innovations for Business Central. Join us at the upcoming Business
Central All Access Virtual Event June 3rd with more than 15 deep dive sessions on what's new in 2020
release wave 1 (April release), also available on-demand.
Registration open now at aka.ms/virtual/businesscentral/2020RW1
Pssst…did we mention it's for free…
Major updates
Get an overview of what you need to know about how a major Business Central update rolls out. It
includes key dates, actions you need to take, and answers some common questions.
See Major Updates of Business Central Online
Update 15.4 for Microsoft Dynamics 365 Business
Central 2019 online release wave 2
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 15.4? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update.

Hotfixes
Link to Hotfixes

Feature changes
Bookmarking a report - rollout is complete. With Update 15.4, all environments now include this feature.

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire wave 2 (release from October 2019 through March 2020), find the link to the release plan here.

Upgrade to 15.4
Please note that new customers will automatically get the latest builds of Business Central (15.4). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Major updates
Get an overview of what you need to know about how a major Business Central update rolls out. It
includes key dates, actions you need take, and answers some common questions. See Major Updates of
Business Central Online.
Preview environments of next major update
Partners should start to prepare for the next major update of Business Central in April. Partners can try
out new functionality in preview environments, give Microsoft feedback and validate your extensions. See
more details in Prepare for major updates with preview environments
Visit our new aka.ms/bcperformance page and start your learning about Business Central performance.
Update 15.3 for Microsoft Dynamics 365 Business
Central 2019 online release wave 2
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 15.3? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update.

Hotfixes
Link to Hotfixes

Feature changes
View Your Reference and External Document No. on sales documents
Skip empty lines in the Account Schedule report
MICR fonts available in Business Central online
New events to unblock printer extensions in Business Central online
Bookmarking a report
Sign-in attempt telemetry in Application Insights for partners

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire wave 2 (release from October 2019 through March 2020), find the link to the release plan here

Upgrade to 15.3
Please note that new customers will automatically get the latest builds of Business Central (15.3). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Changes to Browser Cookie Policy
Avoid disruption by following these steps to prepare for tighter security policies starting February 2020
in Google Chrome and Microsoft Edge. For more information, see Preparing Dynamics NAV or Dynamics
365 Business Central for Upcoming Changes to Browser Cookie Policy.
Using Internet Explorer
From Update 15.3 onwards, users who access Business Central from Internet Explorer will receive a
notification suggesting they consider a different browser. Users who switch to a modern browser, such as
Microsoft Edge, typically observe improved performance and a generally smoother experience. Learn
more about our supported and recommended browsers for Business Central on premises and online.
To support partners who are interested in monetizing the app they have published to AppSource, update
15.3 comes with new options. These options allow partners to understand number, type and state of
Business Central licenses in the current tenant as well as number of allocated seats. That data enables the
partner to implement user-based billing into their apps. To learn more, see Azure AD Licensing.
Visit our new aka.ms/bcperformance page and start your learning about Business Central performance.
Update 15.2 for Microsoft Dynamics 365 Business
Central 2019 online release wave 2
2/6/2023 • 2 minutes to read • Edit Online

Would you like to know what has changed in update 15.2? Below you'll find an overview and relevant links to
what has been done on hotfixes and regulatory features in this update.

Hotfixes
Link to Hotfixes

Feature changes
Add the Name 2 field to customer and vendor cards
Include job information in archived sales and purchase documents
Use VAT clauses on different document types
View item availability by unit of measure
View the number of general journal lines

Release Plan
If you want to get a comprehensive overview of what's new and planned for Business Central online for the
entire wave 2 (release from October 2019 through March 2020), find the link to the release plan here

Upgrade to 15.2
Please note that new customers will automatically get the latest builds of Business Central (15.2). If you are an
existing partner/customer, you will receive an email notification as soon as your environment has been
upgraded.

Good to know
Please find an overview of new "How to videos" recently published on Dynamics 365 YouTube channel for the
Business users and the Functional Consultants. These videos complement the extensive MS Learn and
Documentation content already available for Business Central.
How to set up a customer
How to adjust exchange rates
How to set up a vendor
How to set up purchasers
How to prioritize vendors
How to set up schedule reports
How to set up sales people
How to apply a payment to multiple customer ledger entries
How to reconcile customer payments manually
How to create credit notes and applying across single and multiple ledgers
How to offer discounts and special prices
How to link purchase orders to a sales order
How to set up a new bank account
How to set up an item to sell
How to set up payment methods
How to set up chart of accounts
How to submit a support request
How to report a production outage
How to correct or cancel purchase invoices
How to adjust physical inventory levels
How to work with inventory costing
How to set up an inventory location
How to create purchase order
How to email documents
How to set up documents sending profiles
How to setup categories
How to set up customer approval workflow
How to open a new fiscal year (part of payment methods)
Resources for Help and Support for Dynamics 365
Business Central
2/6/2023 • 9 minutes to read • Edit Online

As a Business Central partner, you have access to resources that can help you support your Business Central
customers, and you have access to resources that can help you be more productive as a partner.
This page outlines the resources available to you.

Product Help
The functionality in the default version of Business Central is described on the learn.microsoft.com site as
described in the following table.

NAME LO C AT IO N DESC RIP T IO N

Business functionality docs learn.microsoft.com/dynamics365/busi Use this library to learn about business
ness-central functionality.

Development and administration docs learn.microsoft.com/dynamics365/busi Use this content to learn how to
ness-central/dev-itpro/ extend, customize, and administrate
Business Central.

AL developer documentation
In the Development in AL section, you find descriptions of processes such as compilation and debugging, and
conceptual information about object types such as tables and events.
The reference documentation of the AL language publishes under the AL Programming umbrella. This content is
partly generated automatically from code, but some of the reference content is maintained by hand. Use the
following landing pages to quickly find the reference content that you need:
Methods
Data Types and Methods in AL
Properties
Properties Overview
Triggers
Triggers Overview
Objects
Table object
Table extension object
Page object
Page extension object
Page customization object
Report object
XMLport object
Query object
Codeunit object
Profile object
Control add-in object
Product versions and Help versions
In general, the Business Central content on the learn.microsoft.com site reflects the latest version of Business
Central online with limited support for earlier versions.
If you support Business Central on-premises, your solution might be one or two versions older than the latest
version. This means that the content in the business functionality documentation might describe functionality
that your users do not have access to. For a better experience, we recommend that you take a copy of our
content at the time when that reflected the version that your on-premises solution is based on and deploy that
to your own website.
The source repo, dynamics365smb-docs, contains packages of Markdown files for major versions and
snapshots of the docs for the previous minor version.
For example, go to https://github.com/MicrosoftDocs/dynamics365smb-docs/releases to get the release that
you need for your solution.
For more information, see the On-premises deployments section in the Configure the Help Experience article.
Customize and extend the user assistance
If you customize or extend Business Central, you are expected to also customize the user assistance so that users
will have access to content that can help them get started, get unblocked, and learn more. For more information,
see User Assistance Model and Configure the Help Experience.

Support
As a Business Central reselling partner, you are an administrator of your customers' Business Central tenants,
and you are the first line of support. You can customize the support experience, and you have access to
information that can help you troubleshoot any issues that your customers report.
For more information, see Technical Support.

Training
You and your customers can find free eLearning content on the Microsoft Learn landing page for Business
Central with suggested collections for getting started, managing financials, and extending Business Central.
The Learn site also includes role-specific learning paths for developers, administrators, and functional
consultants.
Additionally, partners in the Business Central community offer training and books.

Resources
As a partner, you can keep on top of current and upcoming capabilities, and you can share Microsoft's roadmap
with your prospects, for example. This section provides links to places to keep track of for people who are new
to Business Central as well as for people who have been working with the product for years.
This article provides information about the following types of resources:
How to get started as a partner
Where to learn about current and upcoming capabilities
How to make a feature request
Where to find blog posts
Where to find communities
Where to file bugs and issues
Where to contribute to code or docs
Where to ask non-product related questions
Get set up as a partner
If you are not already a Microsoft partner, your company must get set up, and so must you as an employee. For
more information, see Get Started as a Reseller of Business Central Online and Get Started with Building Apps.
Learn about current or upcoming capabilities
You can learn about current and coming capabilities through a number of different resources as outlined in the
following table.

NAME LO C AT IO N DESC RIP T IO N

Release plans learn.microsoft.com/dynamics365/relea Get an overview of upcoming and


se-plans/ recently released capabilities in
Business Central and other Dynamics
365 apps.

Business functionality learn.microsoft.com/dynamics365/busi Use this content to learn about


ness-central/across-business- business functionality in the default
functionality version of Business Central.

Development in the AL language learn.microsoft.com/dynamics365/busi Use this content to learn how to


ness-central/dev-itpro/developer extend and customize Business Central
using the native AL language.

Administrative tasks learn.microsoft.com/dynamics365/busi Use this content to learn how to


ness-central/dev-itpro/administration/ administer Business Central online.

Development in the AL language learn.microsoft.com/dynamics365/busi Use this content to learn how to


ness-central/dev-itpro/developer extend and customize Business
Central.

Security in Business Central learn.microsoft.com/dynamics365/busi Use this content to help you


ness-central/dev-itpro/security/ understand and improve the security
of Business Central.

Compliance learn.microsoft.com/dynamics365/busi Use this content to learn about


ness-central/compliance/compliance- compliance in relation to Business
overview Central.

Performance learn.microsoft.com/dynamics365/busi Use this content to learn how to


ness-central/dev-itpro/performance extend and customize Business
Central.

Integrating with Business Central learn.microsoft.com/dynamics365/busi Use this content to learn how to
using web services ness-central/dev-itpro/webservices/ integrate Business Central with other
products by using web services.

Migrate to Business Central online learn.microsoft.com/dynamics365/busi Use this content to learn how you can
ness-central/dev- move an on-premises solution to
itpro/upgrade/upgrading-to-business- Business Central online.
central-online
NAME LO C AT IO N DESC RIP T IO N

Features not implemented in on- learn.microsoft.com/dynamics365/busi Use this content to learn which
premises deployments ness-central/dev-itpro/features-not- capabilities in Business Central online
implemented-on-premises are not available in Business Central
on-premises deployments.

The Business Central learning catalog learn.microsoft.com/dynamics365/busi Get an overview of role-specific


ness-central/readiness/readiness- training material from Microsoft.
learning-catalog

Free eLearning /learn/dynamics365/business-central Free Business Central collections and


learning paths on Microsoft Learn

Share an idea about a new feature you'd like to have


On the Dynamics 365 Ideas site, you can provide suggestions for new feature and capabilities. Your input goes
directly to Business Central's engineering backlog for investigation and prioritization.
Make sure to search through the list of submitted suggestions, as chances are that someone already submitted
something similar and might have already received votes. Vote if an idea already has been submitted to get it
prioritized on the team's backlog.
Business Central blog posts
The Dynamics 365 blog is where Microsoft publishes announcements, updates, and tips and tricks, including for
Business Central.

NAME LO C AT IO N DESC RIP T IO N

Business Central on the Dynamics 365 https://cloudblogs.microsoft.com/dyna Use this blog to learn about
blog mics365/it/product/business-central/ opportunities, processes, and tools for
the Business Central partner
community.
Some older blog posts are still
available on the Community site for
partners or the Community site for
business users.

Business Central communities


On the Business Central Community site, you have access to the Business Central Forum. You can use this forum
to submit a question and learn from other Business Central community members. MVPs, partners, and
Microsoft employees participate in the conversations.
You can also join the BCUG/NAVUG User Group for Dynamics 365 Business Central and Dynamics NAV, which is
a user-led, user-driven community of more than 26,000 users, partners, and MVPs.
Summary of where to file bugs and issues
As a partner, you have different support channels depending on what type of issue you want support for. The
following list outlines the various channels.

ISSUE T Y P E SIT E

Submit support request on behalf of your Business Central Start at the Business Central administration center where
online customers you can easily submit a support request in the Power
Platform admin center

Report bug in a preview or beta version The MS Collaborate site


ISSUE T Y P E SIT E

Collaboration on the AL language and developer experience The AL Developer Preview GitHub repo

As an ISV, report an issue in production code, such as a The Partner Center Support site - choose the Marketplace
problem with Microsoft's application, upgrade, or telemetry Offers category, and then choose the relevant category in
the Problem type field, such as Dynamics 365 Business
Central Development > Core Application issues. You'll be
asked to check resources and then to provide issue details.

Report bug in supported in-market versions of Business The Support for business site
Central on-premises

IMPORTANT
To submit support requests on behalf of your customer, you must be a delegated admin on the customer tenant. Your
company must also have the Advanced or Premier support plan. For more information, see the Escalating support issues
to Microsoft section.

For more information, see Technical Support for Dynamics 365 Business Central.
Engage with us on GitHub
GitHub brings together communities of developers and other contributors to discover, share, and build software.
Here are some useful repositories for Business Central:
Microsoft AL
For collaboration on the AL development environment in Visual Studio Code, use the GitHub repo here:
https://github.com/microsoft/al
Microsoft AL application add-ons
There are a couple of ways to engage with us in the https://github.com/microsoft/ALAppExtensions repo:
You can grab the code and contribute to the published apps.
If you're building your own app and need something specific from us, such as an event, you can help
improve the general extensibility of the business logic.
BcContainerHelper
Use this repo to collaborate around the source code and the scripts of BcContainerHelper PowerShell
module for Business Central: https://github.com/Microsoft/NavContainerHelper
Business Central Tech Samples
Find Microsoft's prototypes, experiments to test performance, and other examples of what Microsoft's
engineers get up to apart from shipping production code, in the https://github.com/microsoft/BCTech
repo.
Documentation
The product Help and developer and administration content is based on GitHub as well, and you can
collaborate and extend the docs. The GitHub repos are:
Product Help (English US): https://github.com/MicrosoftDocs/dynamics365smb-docs
Developer and administration content: https://github.com/MicrosoftDocs/dynamics365smb-devitpro-
pb
For more information, see Extend and Collaborate on the Help.
Non-product related questions
On occasion, as a partner, you will run into questions that are not directly related to the product. The following
list outlines how to get answers to those questions.

F O R Q UEST IO N S REL AT ED TO C O N TA C T

Problems with listing or publishing apps to AppSource due The Partner Center Support site - choose the Marketplace
to Commercial Marketplace issues offers category, and then choose the relevant category in
the Problem type field, such as Availability > Dynamics
365 Business Central offer.

Licensing or PSBC agreements Email MBS Orders or MBS Agreements, respectively

Microsoft Partner Network, Partner Center, Cloud Solution The Partner Center Support site
Provider program

Payments, credit terms, checks, wire, or similar Email MBS Accounting

Technical issues with PSBC, PartnerSource, or Order Central Email IT MBS Support

Incentives Email CSA Team

Cloud Solution Provider incentives Email Online Channel Incentives Support

CSA/Ocina escalations Email NAOC Channel Incentives Escalations

Volume licensing The Call Logging Tool site or email Online Licensing

Trials
Giving prospects access to a pre-configured trial of Business Central is an elegant way to introduce them to
Business Central. You can use the standard trial provided by Microsoft, or you can prepare your own including
relevant extensions.
For more information, see Preparing Demonstration Environments.

See also
Technical Support
Configuring the Help Experience
Migrate Legacy Help
User Assistance Model
The Business Central Administration Center
Legal Landing Page for Microsoft Dynamics 365
Business Central Online
2/6/2023 • 2 minutes to read • Edit Online

This article provides links to legal information for Business Central online.

Product Terms
Commercial Licensing Terms for the Microsoft Customer Agreement program

Microsoft AL Language
AL Language - Terms of Use
AL Extension Third Party Notice

Envestnet Yodlee - Bank Feeds


Envestnet Yodlee - Bank Feeds Terms and Conditions

Trial Services terms


Trial Services terms

Lifecycle policy
Lifecycle policy for Business Central online

See Also
Privacy FAQ
Legal Resources for Business Central On-Premises
Developer and Administration Help for Microsoft Dynamics 365 Business Central
Technical Support for Dynamics 365 Business
Central
2/6/2023 • 5 minutes to read • Edit Online

Each customer of Business Central has a partner who assists with technical support. As a Business Central
reselling partner, you are an administrator of your customers' Business Central tenants, and you are the first line
of support. You will get requests for support from your customers that you must triage, investigate, and either
resolve or escalate to Microsoft.
In this section, you can learn about the tools that are available to you to help you troubleshoot your customers'
Business Central.

Configuring the support experience


Because you are the first line of support for your customers, you must make it easy for them to contact you.
They can find your contact information in the Help and Support page.

IMPORTANT
You must have set up users in your own tenant in Partner Center as either Admin agent or Helpdesk agent, and they
must have delegated administration privileges in your customer's Business Central to support the customer. For more
information, see Delegated Administrator Access to Business Central Online.

To supply your support contact information in the administration center


1. In the Business Central administration center, choose the environment that you want to specify your contact
details for, such as Production, and then, in the Suppor t menu, choose Manage Suppor t Contact .
2. Fill in the Name , Email address , and the Website fields, so that your users know how to contact you for
technical support.
3. Optionally, choose the Apply to all environments checkbox if you want to add the same details to all
related environments for this tenant.
Your customer can now contact you if they experience problems and need help. If you also cannot resolve a
reported issue, escalate the issue to Microsoft. For more information, see Managing Technical Support.
On-premises deployments
In on-premises deployments of Business Central, the Help and Suppor t page does not contain the section for
contacting technical support. Instead, you can enter an agreement with your customer's administrator about
how and when to contact you.
There are two other links in the Help and Suppor t page that you can customize:
Blog
Specifies a link to where your customers can access a blog about their solution
Coming soon
Specifies a link to where your customers can access a roadmap for future changes
If you choose to not modify these settings, then the links go to Microsoft's blog and release notes.
For more information, see Configuring Business Central Web Server Instances.

Getting support for extension issues


As a partner, you must identify if the issue is caused by application logic or platform behavior:
If the issue is caused by application logic, you must identify the publisher of the extension.
If the extension is a per-tenant extension, as a partner, you must fix the issue.
If the extension is an AppSource extension, you must contact the AppSource partner that developed the
extension.
If the extension is published by Microsoft, you must contact Microsoft support.

Troubleshooting and support


The Business Central administration center is your primary tool to support your customers. However, you can
also sign in to the customer's Business Central as the delegated admin for troubleshooting.
For more information, see Managing Technical Support.

Monitor service health


Both as an internal admin and as a delegated admin, you can help users determine the cause of their problems
in different ways before you have to escalate the issue to Microsoft Support. The starting point is the Business
Central administration center where you can access telemetry for the tenant and check the status of already
reported outages. For more information, see Managing Production and Sandbox Environments in the Admin
Center.
The Microsoft 365 admin center provides an overview of service health across Microsoft services. Select
Preferences to receive service health email notifications about incidents across Business Central, Microsoft
365, and other Microsoft services. For more information, see How to check service health. If you manage more
than one tenant, see View service health for all accounts.
As a partner, use the Partner Center to get an overview of service health for each customer. For more
information, see Check service health for a customer in the Partner Center content. You can also use APIs for
automated service notifications for Azure Insights & Office 365 service communications.
Summary of where to file bugs and issues
As a partner, you have different support channels depending on what type of issue you want support for. The
following list outlines the various channels.

ISSUE T Y P E SIT E

Submit support request on behalf of your Business Central Start at the Business Central administration center where
online customers you can easily submit a support request in the Power
Platform admin center

Report bug in a preview or beta version The MS Collaborate site

Collaboration on the AL language and developer experience The AL Developer Preview GitHub repo

As an ISV, report an issue in production code, such as a The Partner Center Support site - choose the Marketplace
problem with Microsoft's application, upgrade, or telemetry Offers category, and then choose the relevant category in
the Problem type field, such as Dynamics 365 Business
Central Development > Core Application issues. You'll be
asked to check resources and then to provide issue details.
ISSUE T Y P E SIT E

Report bug in supported in-market versions of Business The Support for business site
Central on-premises

IMPORTANT
To submit support requests on behalf of your customer, you must be a delegated admin on the customer tenant. Your
company must also have the Advanced or Premier support plan. For more information, see the Escalating support issues
to Microsoft section.

TIP
When you submit your first support ticket as a partner, you must specify details about your company's support plan. If
you or your colleagues do not know these details, contact your Microsoft rep.

Non-product related questions


On occasion, as a partner, you will run into questions that are not directly related to the product. The following
list outlines how to get answers to those questions.

F O R Q UEST IO N S REL AT ED TO C O N TA C T

Problems with listing or publishing apps to AppSource due The Partner Center Support site - choose the Marketplace
to Commercial Marketplace issues offers category, and then choose the relevant category in
the Problem type field, such as Availability > Dynamics
365 Business Central offer.

Licensing or PSBC agreements Email MBS Orders or MBS Agreements, respectively

Microsoft Partner Network, Partner Center, Cloud Solution The Partner Center Support site
Provider program

Payments, credit terms, checks, wire, or similar Email MBS Accounting

Technical issues with PSBC, PartnerSource, or Order Central Email IT MBS Support

Incentives Email CSA Team

Cloud Solution Provider incentives Email Online Channel Incentives Support

CSA/Ocina escalations Email NAOC Channel Incentives Escalations

Volume licensing The Call Logging Tool site or email Online Licensing

See Also
Inspecting and Troubleshooting Pages
The Business Central Administration Center
Managing Technical Support
Deployment Overview
Administration of Business Central Online
Administration of Business Central On-Premises
Provide technical support (Microsoft Partner Center)
Providing support to your customers (Microsoft Partner Center)
Dynamics 365 Business Central User Assistance
Model
2/6/2023 • 13 minutes to read • Edit Online

The Business Central user assistance model is based on the following principles:
Get started
Home pages give easy access to key tasks so users can easily get started with work every day. Embedded
user assistance implemented as teaching tips help users understand new or unfamiliar pages, and
checklists make it easy to get started in a new company.
Get unblocked
Embedded user assistance implemented as tooltips answers most immediate questions about what fields
and actions do.
Learn more
The Help menu and Learn more links on tooltips and teaching tips provide context-sensitive access to
Help articles with more information.
Apps, extensions, and customizations are expected to follow the same model by applying tooltips to controls on
page objects, and by providing links to Help for their functionality. For more information about customizing and
extending the user assistance, see Extend and Collaborate on the Help and Configure the Help Experience.
In this article, we'll talk about the user assistance model itself and what it does.

Help users get started


The user assistance concept of Get Started is not just about getting started with Business Central on the first day.
It's also about getting started all the other days, and about getting started with infrequent and unfamiliar tasks.
Any new product can be baffling at first. For infrequent tasks, even after months of using the product, users can
find it hard to remember where that report is, or how to fill in that form.
The default version of Business Central online includes in-product tours to introduce the first users of a new
tenant to the general user interface and the most used pages. The in-product search makes it easy to find pages
or reports - provided that you remember what they're called.
We strive to make Business Central easy to get started with in the browser and in the apps for desktop and
mobile devices. Assistance in the shape of wizards is helpful for setup or filling in data for a complicated report,
for example. Home pages that are designed for a particular role or job help users get started with their daily
work – they can easily get to their most important tasks, and that means that Business Central helps them get
their work done more efficiently. Similarly, in-product links to videos give new users a quick introduction to how
the product works.
Onboarding checklist
APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

To help users set up Business Central on the first day, partners can add required steps to the checklist. The
checklist is intended to help users fill in necessary information and help themselves get familiar with Business
Central. For more information, see Get Users Started with the Checklist.
Teaching tips and tours
APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

2021 release wave 1 brought an interpretation of teaching tips that you can add to your Business Central
solution. Use the teaching tips from the onboarding framework to introduce users to complex pages, and to
build tours that help users understand the purpose of a complicated area, for example. Create the teaching tips
in code by setting the AboutTitle and AboutText properties.

NOTE
Teaching tips supplement the tooltips that provide descriptions for all fields and actions.

There are different rules for tooltips and teaching tips.

TO O LT IP P O IN T IN G AT A F IEL D C A P T IO N T EA C H IN G T IP P O IN T IN G TO A F IEL D

Guidance for tooltips: Guidance for control teaching tips:

Every field and action has a tooltip. Only the most important fields/actions have a
teaching tip.
Answers the question What is this?
Answers the question What can I do with this field or
Relevant for everything since every field/action has a action?
definition.
Isn't relevant for every field/action.

Teaching tips guides users to fields/actions to be


discovered and focus on.

For more information, see Teaching tips and in-app tours for onboarding users.
Help pane
APPLIES TO: Business Central 2022 release wave 1 and later

When the user opens the Help pane, they see content and links to learn more based on where they are in the
product. Once users discover the Help pane, they will be able to help themselves get unblocked, we hope.
The Help pane shows up to four types of links:
A link about the current page
At the top of the pane, a card repeats the current page's teaching tip, if one exists. If there is no teaching
tip, then the card provides a single link to an article about the page. This link is based on the page-level
configuration of context-sensitive Help.
If Business Central can't find the relevant link, we show the landing page on learn.microsoft.com. For
example, if the page was part of an app that didn't add context-sensitive Help mapping to Business
Central, the Learn link defaults to the landing page.
Links to related articles from Microsoft Docs
These links are related to the current page and will change if you move to another page. The links are
limited to the learn.microsoft.com site. If there are more than three links, choose the Show more link to
expand the card. Choose any link, and the related article will open in a new browser tab.
Links to content for apps on the current page
These links are based on any app that extends the page or defines the page. These links are based on the
page-level configuration of context-sensitive Help.
Links to other resources
Three links are always available in the Help pane: Links to the Help & Suppor t page inside Business
Central, the Keyboard Shortcuts article, and the Business Central community. These links are always
shown, and the list cannot be modified.
If the automatically generated links do not answer the user's question, then the user can use the Search field to
search Microsoft's content, both documentation and e-learning material. Currently, search in the Business
Central Help pane cannot access sites other than the learn.microsoft.com site, including Microsoft Learn.

Help users get unblocked


Even the best designed user interface can still be confusing to some. It can be difficult to predict what users will
find confusing, and that is why the base application includes descriptions for all controls and actions that can be
accessed when you choose the caption of the control or action. In combination with descriptive captions and
instructional text, these tooltips, or callouts, constitute the larger part of our current implementation of
embedded user assistance, which is an important principle in today's world of software design.
The tooltips help users unblock themselves by providing an answer to the most likely questions the users might
have, such as "What data can I input here?" or "What is the data used for?". Keep tooltips in mind when you
develop the user interface of your solution.

These descriptions are applied to controls on pages rather than table fields. Table fields can be read-only in one
page and editable in another, so the tooltips describe the difference. In Business Central, this type of "What is this
field?" content is embedded in the page objects, and resource files can be used for translated user interfaces. For
more information, see Working with Translation Files.
Most tooltips end with an automatically generated link to learn more as described in the Help users learn more
section; however, tooltips for actions do not have Learn more links:
TIP
Users can always use the Ctrl+F1 keyboard shortcut to access the learn more content that is configured for the currently-
selected item in the user interface. In 2022 release wave 1 and later, Ctrl+F1 opens the Help pane with automatically
generated links to related content from Microsoft and partners.

The tooltips in Business Central are conceptually similar to field descriptions in Dynamics 365 Finance and
related apps, and teaching tips in the Universal Windows Platform's Fluent Design guidelines. The onboarding
framework in 2021 release wave 1 added another interpretation of teaching tips that you can add to your
Business Central solution. For more information, see Teaching tips and in-app tours for onboarding users.
Guidelines for tooltip text
The Microsoft user assistance model requires a tooltip for all controls of type Action and Field that exist on page
objects. Follow these guidelines:
If the control is a field, begin with the verb Specifies.
If the control is an action, begin with a verb in the imperative form , such as Calculate or View .
Include the most valuable information that users need to perform the task(s) that the field or action
supports.
For example, for the Post action, do not write Post the document. Write, for example, Update ledgers with
the amounts and quantities on the document or journal lines.
Describe complex options in tooltips for option fields.
Use a colon to call out the option name and its description. See example 3 below.
Try to not exceed 200 characters including spaces.
This makes the tooltip easier to scan so the user can get unblocked quickly. However, the UI will render
longer tooltip text if you want to provide more detailed user assistance.
Do not use line breaks in the tooltip text.
The tooltip cannot render formatting or line breaks.
Examples
The following table shows examples of effective tooltips.

C O N T RO L N A M E TO O LT IP

Password field Specifies your company's password to the service that


converts bank data. The password that you enter in this field
must be the same as on the service provider's sign-on page.
(175 characters including spaces)

Entries action View the history of transactions that have been posted for
the customer.
(72 characters including spaces)
C O N T RO L N A M E TO O LT IP

Account Type field Specifies the purpose of the account. Total: Used to total a
series of balances on accounts from many different account
groupings. To use Total, leave this field blank. Begin-Total: A
marker for the beginning of a series of accounts to be
totaled that ends with an End-Total account. End-Total: A
total of a series of accounts that starts with the preceding
Begin-Total account. The total is defined in the Totaling field.
(522 characters including spaces)

Help users learn more


The content that Microsoft publishes under the user assistance concept of Learn more is intended to answer
those questions that the user interface (including the tooltips) cannot answer, such as where that page fits into
the bigger workflow, or what comes next, or what would be the alternative.
Users can access this content either through the Learn more link in tooltips, by choosing the Help menu, or by
using the Ctrl+F1 keyboard shortcut.
Links in the Help pane
APPLIES TO: Business Central 2022 release wave 1 and later

The Learn more links on tooltips and the Ctrl+F1 shortcut now open the Help pane. In most cases, the pane
shows the following types of content:
A link about the current page
At the top of the pane, a card repeats the current page's teaching tip, if one exists. If there is no teaching
tip, then the card provides a single link to an article about the page. This link is based on the page-level
configuration of context-sensitive Help.
If Business Central can't find the relevant link, we show the landing page on learn.microsoft.com. For
example, if the page was part of an app that didn't add context-sensitive Help mapping to Business
Central, the Learn link defaults to the landing page.
Links to related articles from Microsoft Docs
These links are related to the current page and will change if you move to another page. The links are
limited to the learn.microsoft.com site. If there are more than three links, choose the Show more link to
expand the card. Choose any link, and the related article will open in a new browser tab.
Links to content for apps on the current page
These links are based on any app that extends the page or defines the page. These links are based on the
page-level configuration of context-sensitive Help.
Links to other resources
Three links are always available in the Help pane: Links to the Help & Suppor t page inside Business
Central, the Keyboard Shortcuts article, and the Business Central community. These links are always
shown, and the list cannot be modified.
The partner-provided links are based on the mechanism for adding links through app-level and page-level
configuration. For more information, see Configure Context-Sensitive Help.
The following screenshot illustrates the Help pane when it is opened from the Purchase Invoice page.
In this case, the Purchase Invoice page has not been extended by any apps. If two apps had extended the page,
their page-level and app-level configuration would be used to add links on a card after the Related articles from
Microsoft Docs card.
The base version of Business Central uses content that is published to an online library,
(learn.microsoft.com/dynamics365/business-central), so that it can also serve as onboarding material and as
feature overviews that you can share with prospects. The content is written in MarkDown, and our source files
are available in a public GitHub repo that you can extend for your customers.

NOTE
Currently, Business Central does not require the Help for your own functionality to be created in a specific format. But we
expect you to make it available on a website that the users of your functionality can access. For more information, see
Configure Context-Sensitive Help.

For the base version of Business Central, free online learning is also available on Microsoft Learn. For more
information, see the Business Central Learning Catalog.
Feedback and contributions
On learn.microsoft.com, each article has two buttons at the end of the article. The Product feedback button
sends you to the Ideas site, and the Sign in to give documentation feedback button lets you submit feedback
about the content through GitHub. In both cases, you must create an account if you do not already have one. For
product feedback, you must sign in with your work or organizational email account. For access to GitHub, you
can use any email address when you create an account.
We welcome your contributions, both as pull requests with suggestions or corrections to the content, and as
GitHub Issues with bugs or questions. However, we can only accept feedback and contributions to the content in
the dynamics365smb-docs and dynamics365smb-devitpro-pb repos. Also, we cannot address issues or
questions about the product.

IMPORTANT
If you have feedback about translations, you can report a GitHub issue in the dynamics365smb-docs repo.

For more information, see Extend and Collaborate on the Help.


Working in MarkDown
If you fork one of our repos, you will be authoring in MarkDown. We recommend that you learn the basics by
referring to the Docs Markdown reference section in the Learn Contributor Guide.
The Docs Authoring Pack for VS Code can aid with MarkDown authoring and validation in Visual Studio Code.
However, you can also use other text editors to edit MarkDown.
For other tips and tricks, see Extend and Collaborate on the Help and the blog post Collaborate on content for
Business Central.

Translate the Help


If you want to deliver a localization app, or if you want to deliver your functionality in more than one country,
you will want to translate the Help as well as the product. We suggest that you take a look at the Microsoft
Dynamics 365 Translation Service, which is available as preview in Microsoft Dynamics Life Cycle Services. For
more information, see Translate documentation files.
The user interface text, including the tooltips, is translated as part of the application. For more information, see
Working with Translation Files.

Style
At Microsoft, we are in process of simplifying and unifying our style guides. To get to know the Microsoft style,
use the Microsoft Writing Style Guide as a good starting point. The Business Central follows most of the
guidelines in the Microsoft Writing Style Guide with exceptions for industry terminology and other product-
specific issues.

Get notified about changes through an RSS feed


To subscribe to a Really Simple Syndication (RSS) feed of all updates that are to the content on
learn.microsoft.com across the developer and administration content for Business Central, use the following
link:
RSS feed

NOTE
The RSS feed returns a list of the 100 articles most recently updated. The list is sorted by date, but it can take up to a
week before the most recently updated articles make it to the list.

See Also
Configure the Help Experience
Adding Help Links from Pages, Reports, and XMLports
ToolTip Property
InstructionalText Property
Development of a Localization Solution
Translate documentation files
Resources for Help and Support
Blog post: Extending and customizing the Help
Blog post: Collaborate on content for Business Central
Docs Contributor Guide
Docs Authoring Pack for Visual Studio Code
Microsoft Cloud Style Guide (requires login)
Microsoft Writing Style Guide
Onboarding experiences in Business Central
Teaching tips and in-app tours for onboarding users
Configuring the Help Experience for Dynamics 365
Business Central
2/6/2023 • 11 minutes to read • Edit Online

The default version of Business Central comes with conceptual overviews and other articles that publish to the
learn.microsoft.com/dynamics365/business-central/ site. This location is accessible from the Help menu and
through the Learn More links in all tooltips. Each extension that you add will include its own tooltips and links
to Help that can be accessed through the Learn More links and the Ctrl+F1 keyboard shortcut.
But what if you want to deploy Business Central locally? Or if you have a vertical solution so that you want to
refer your customers to your own website for Help? Or if you have a legacy Help collection based on the
Dynamics NAV Help Server? These and other scenarios are also supported in Business Central.

Apps for online tenants


When you build an app for Business Central using the AL developer experience, you are expected to apply
tooltips and context-sensitive links to Help content on a website in accordance with the user assistance model.
For more information, see the Deploy content to your website section and the Configure Context-Sensitive Help
article.

TIP
The website does not have to be publicly accessible, but it must be accessible to all users of the solution that it supports.

You can add Microsoft's content to your website, or you can deploy just your own content. The choice is yours
and depends on the requirements of your users, the size of your app, and the amount of customization you
want to make. The custom Help toolkit includes tools that can help you prepare and deploy content. For more
information, see Custom Help Toolkit.

TIP
You are not required to use the toolkit. It's available for you to use if it makes sense for your Business Central solution.

If your solution extends Business Central online with additional capabilities, we recommend that you set up a
website with your own content. To build the HTML files, use any third-party tool that you prefer, such as DocFX.
For inspiration for how to create a website that can host your content, explore this tutorial. The tutorial
demonstrates how to create a static web app and add a search service in a few relatively straightforward steps.

On-premises deployments
For deploying Business Central on-premises, you can choose between using any online website or the legacy
Dynamics NAV Help Server, and you can configure different Help experience for each Business Central Web
Server instance. For supported versions, the legacy Dynamics NAV Help Server component is a simple website
that requires your Help to be in a specific format (HTML files). Other types of websites can host any content that
you want to make available. Your choice depends on the needs of your solution and your users. If you add
configuration for an online library, you must remove any settings for Help Server.
IMPORTANT
The legacy Dynamics NAV Help Server component was deprecated and removed in 2021 release wave 1 (version 18). We
recommend that you invest in a different type of website. For more information, see the deprecation notice.

TIP
The content on the learn.microsoft.com/dynamics365/business-central/ site and in the various GitHub repos reflects the
latest version of Business Central, unless otherwise specified.
If, for some reason, you need a copy of Microsoft's content, then get it close to the time the subsequent major version of
Business Central becomes available. For example, if you are deploying version 19.4, you could have taken a snapshot of
the content in GitHub before version 20.0 became available.

The source repo, dynamics365smb-docs, contains packages of Markdown files for major versions and
snapshots of the docs for the previous minor version.
For example, go to https://github.com/MicrosoftDocs/dynamics365smb-docs/releases to get the release that
you need for your solution.
Online library
To display content from a website that hosts your user assistance content, specify the URL in the settings for the
Business Central Web Server. The navsettings.json file must contain the following setting in the
ApplicationIdSettings element:

{
"NAVWebSettings": {
// [...more keys]
},
"ApplicationIdSettings": {
//BaseHelpUrl: The location of Help for this application.,
"BaseHelpUrl": "https://mysite.com/{0}/documentation/",
// [...more keys]
}
}

NOTE
Replace the value of the BaseHelpUrl key with the URL for your own website. The parameter, {0}, represents the locale of
the browser that the user is using, such as en-us or da-dk, and is set automatically at runtime.

For more information, see Configuring Business Central Web Server Instances.

TIP
The website does not have to be publicly accessible, but it must be accessible to all users of the solution that it supports.

TIP
You are not required to use the toolkit. It's available for you to use if it makes sense for your Business Central solution.

For example, if you deploy Business Central on-premises, you might want to set up a dedicated website with
customer-specific content that includes customized content from Microsoft. However, Microsoft's content is
optimized for the learn.microsoft.com site.
Legacy Help Server
APPLIES TO : 2020 release wave 2 and earlier versions

If you want to use Help Server, then you must specify the server and port in the installation options. The Help
Server website can also serve as a starting point for adding a library to your existing website, for example.

IMPORTANT
In version 18 and later versions, if you use the legacy Dynamics NAV Help Server component as a standalone website,
then you must use the settings for the online library that is described in the previous section.

For more information, see Configuring Microsoft Dynamics NAV Help Server in the developer and
administration content for Dynamics NAV.

IMPORTANT
If you use Help Server, context-sensitive Help does not work anymore. Neither the UI-to-Help mapping functionality that
is described in Configure Context-Sensitive Help, nor the original Help lookup mechanism that was based on filenames
that reflected the object IDs, such as N_123.htm for the page object with the ID 123. For more information, see the blog
post Reusing classic object-based Help on your Dynamics 365 Business Central Help Server.

TIP
If you are upgrading from Microsoft Dynamics NAV 2013 R2 or later, you can reuse your existing Help Server content by
simply replacing the product name and make any other changes that apply to your Business Central environment. But we
encourage you to deploy the content to another website.

You can still download the files that were made available for Microsoft Dynamics NAV 2017. The download
consists of 45 CAB files with the content from the Dynamics NAV 2016 DVD rebranded to Microsoft Dynamics
NAV 2017. The download includes CAB files with the W1 application Help translated into each of the supported
languages plus the local functionality for the country/region where that language is spoken. There are also CAB
files with local functionality in English. The files were published as a single download so each administrator
could choose exactly the files that they needed at the time. For more information, see Microsoft Dynamics NAV
2017 Classic Help Download.
However, you must switch to the UI-to-Help mapping functionality that is described in Configure Context-
Sensitive Help.

Deploy content to your website


Currently, Business Central has no firm requirements for the website that hosts your online library for your
Business Central online or on-premises. You can deploy your content using any tool and process including the
following:
Azure Static Web Apps
Azure App Service
Third-party services such as MkDocs
Any website that can render MarkDown files using a customization of the DocFX Flavored MarkDown engine
You can see an example of how to deploy content to an Azure web app in the article Deploy custom help to
Azure. That article also describes how you can build a search service for your website. Another example is in the
Overview of adding search to a website with Python tutorial in the Azure docs. The step for adding a search
service is currently not relevant for Business Central, but you might find the guidance helpful anyway.

IMPORTANT
Currently, search in the Business Central Help pane cannot access sites other than the learn.microsoft.com site, including
Microsoft Learn.
However, to help prepare for the day when partner-provided and customer-provided content can also be indexed and
found by in-product search and the help pane, get your content deployed to a website and make it discoverable.

In versions older than 2022 release wave 1, the in-product search includes searching content on the
learn.microsoft.com/dynamics365/business-central site. In 2022 release wave 1 and later, this search is replaced
by the search capabilities of the Help pane. But the restrictions remain the same.
Optional: Get Microsoft's content
If you deploy a solution that customizes Microsoft's default application, then you might want to include a
customized version of Microsoft's business functionality content on your website. In most other cases, such as if
you build an add-on app, you do not need Microsoft's content. Your own content will supplement Microsoft's
content in the same way that your code supplements Microsoft's code. For more information, see Configure
Context-Sensitive Help.

IMPORTANT
The remainder of this section is for those people who need a copy of Microsoft's content to deploy to a website along
with their own content. In many cases, you do not need to customize Microsoft's content, and this section is irrelevant for
you. However, if you deploy a customized solution on-premises or in a closed environment, then you might need to
include Microsoft's content in your Help website.

We encourage you to use apply the ROBOTS: NOINDEX, NOFOLLOW metadata to any customized versions of
Microsoft's content. The intent is that search engines will find Microsoft's original content on the
learn.microsoft.com site rather than any customizations that you and hundreds of other may have published. Set
the metadata in the individual files, or set it in the globalMeta section of docfx.json if you build using docfx.exe.
For an example, see the ui-work-with-notes.md file in GitHub, which we have deprecated but kept in the repo as
an example.
If you use the docfx.json file to build HTML files for non-Microsoft functionality, then set the value of the ROBOTS
property when you build Microsoft's content. You can also add other global metadata, or metadata that applies
to specific subfolders.
Microsoft's source files are available as downloadable packages for each major release in the
https://github.com/MicrosoftDocs/dynamics365smb-docs/ GitHub repo in English (US) only.

IMPORTANT
The HTMLFromRepoGenerator tool is being deprecated. To generate HTML files from Markdown, use another tool, such
as DocFX.
The language-specific repositories are also being deprecated, and will no longer be available at the end of the 2022
calendar year.
TIP
The content on the learn.microsoft.com/dynamics365/business-central/ site and in the various GitHub repos reflects the
latest version of Business Central, unless otherwise specified.
The source repo, dynamics365smb-docs, contains packages of Markdown files for major versions and snapshots of the
docs for the previous minor version.
For example, go to https://github.com/MicrosoftDocs/dynamics365smb-docs/releases to get the release that you need
for your solution.

Use any tool or script that you prefer. If you want to create your own tooling and processes around DocFX,
examples are available in the Build HTML files section of the contributor guide.

IMPORTANT
We encourage you to use apply the ROBOTS: NOINDEX, NOFOLLOW metadata to any customized versions of Microsoft's
content. The intent is that search engines will find Microsoft's original content on the learn.microsoft.com site rather than
any customizations that you and hundreds of other may have published. Set the metadata in the individual files, or set it
in the globalMeta section of docfx.json if you build using docfx.exe. For an example, see the ui-work-with-notes.md file
in GitHub, which we have deprecated but kept in the repo as an example.
If you use the docfx.json file to build HTML files for non-Microsoft functionality, then set the value of the ROBOTS
property when you build Microsoft's content. You can also add other global metadata, or metadata that applies to specific
subfolders.

We suggest that your website clearly indicates what is under Microsoft's copyright and what is under your own
copyright. You are still welcome to make any relevant customizations of Microsoft's content, and to deploy this
customized content to your own website. But to help users clearly identify whether a given search result applies
to their Business Central experience or not, do not apply a title suffix such as Microsoft Docs. We also discourage
reproduction of the visual styling of the learn.microsoft.com site for the same reason.

Fork the Microsoft repos, and customize or extend the content


If you want to customize or extend the Microsoft Help, you can fork our public repo for the source repo in
English (US) at https://github.com/MicrosoftDocs/dynamics365smb-docs. For more information, see Extend and
Collaborate on the Help.

TIP
You are not required to use the toolkit. It's available for you to use if it makes sense for your Business Central solution.

See Also
User Assistance Model
Adding Help Links from Pages, Reports, and XMLports
Migrate Legacy Help to the Business Central Format
Building Your First Sample Extension With Extension Objects, Install Code, and Upgrade Code
Building an Advanced Sample Extension
Development of a Localization Solution
Resources for Help and Support
Blog post: Extending and customizing the Help
Blog post: Collaborate on content for Business Central
Blog post: Reusing classic object-based Help on your Dynamics 365 Business Central Help Server
Working with Dynamics NAV Help Server
Docs Contributor Guide
Docs Authoring Pack for Visual Studio Code
Configure Context-Sensitive Help
2/6/2023 • 7 minutes to read • Edit Online

A key pillar of helping users help themselves is to give them access to Help for the particular part of Business
Central that they are working in. When you build an app for Business Central online, we expect you to provide
Help for your solution that can be accessed from the Learn more links on tooltips. For more information, see
Help users learn more.
Starting in 2022 release wave 1, version 20, the Learn more links open the Help pane. The same mechanism
makes sure that your page-level links are available in the Help pane.
The Learn more links are generated based on two configuration settings:
App-level configuration of the URL
Page-level configuration of page-specific article

App-level configuration
Specify where the Help for your functionality is published in the contextSensitiveHelpUrl property in the
app.json file. For example, if you publish your content to https://mysite.com/documentation :

"contextSensitiveHelpUrl": "https://mysite.com/documentation/",

In this example, when the user is using your app's functionality, the contextSensitiveHelpUrl property specifies
that the links to Help will go to the mysite.com site. When the user is using functionality from the base
application, then the Help calls will go to the learn.microsoft.com site.
If your app only supports a limited number of locales, you can specify that as well as shown in the following
example:

"contextSensitiveHelpUrl": "https://mysite.com/{0}/documentation/",
"supportedLocales": [
"en-GB", "en-IE
],

The contextSensitiveHelpUrl and supportedLocales properties specify that the links to the Help for page objects
in this app must go to the mysite.com site, but that the site only supports those two languages. All other Help
calls from objects in this app will go to the default locale on the specified webserver, in this case the equivalent
of https://mysite.com/en-GB/documentation/my-feature .

TIP
For tips and tricks for how to deploy content to your own website, see the Configuring the Help Experience for Dynamics
365 Business Central.

Help calls for Microsoft objects will continue to go to the learn.microsoft.com site.
Localization apps
Specifically for localization apps that translate Business Central into languages that are not offered by Microsoft,
the app.json file must be set to specify the destination of links to Help as shown in the following example:

"helpBaseUrl": "https://mysite.com/{0}/documentation/",
"supportedLocales": [
"ca-es"
],

The helpBaseUrl property represents the URL that will be used to overwrite the default Microsoft help link,
which is (/{0}/dynamics365/business-central) . The value of the property must contain a placeholder for the
user's locale culture, {0} .
The property specifies the list of locales that are supported by the URL specified in the
supportedLocales
helpBaseUrl property and used in the translation app. If the user's current locale is among the
supportedLocales of the extension, the user will be re-directed to the help base URL that you specified.

In this example, the helpBaseUrl and supportedLocales properties specify that the links to the Help must go to
the mysite.com site when the user is using the product in Catalan. If the user switches the application language
to English (US), then the Help calls will go to the learn.microsoft.com site.

Page-level configuration
Your target website is expected to have a default page that will display if nothing else is specified. But for each
page or page extension in your app, you can specify the Help page that describes this page or the fields that the
page extension adds to the page. You can do that using the ContextSensitiveHelpPage property as shown in the
following example:

page 50101 "Reward Card"


{
PageType = Card;
SourceTable = Reward;
ContextSensitiveHelpPage = 'sales-rewards';

In this example, the app contains a page object that is mapped to the sales-rewards Help file on the website that
the app.json specifies. As a result, the Learn more link in the tooltips for this page will go to the equivalent of
https://mysite.com/documentation/sales-rewards .

Similarly, the following code example shows a page extension object that sets the ContextSensitiveHelpPage
property so that the Learn more link in tooltips for the fields that this page extension adds to the Customer Card
will go to the https://mysite.com/documentation/sales-rewards rather than the default location at
learn.microsoft.com:

pageextension 50104 "Customer Card Ext" extends "Customer Card"


{
ContextSensitiveHelpPage = 'sales-rewards';
layout
{...}
}

You can use the ContextSensitiveHelpPage property to direct Help calls from multiple page objects or actions to
the same article. For example, Microsoft has chosen to group the context-sensitive links depending on the
granularity of the Help for specific area in the base application. If the Help for a specific area is made more
granular, then the context-sensitive Help mapping is updated accordingly.
Your target website is expected to have a default page that will display if no other page is appropriate. For every
page where ContextSensitiveHelpPage is not set, this default Help page will be shown.
For page extensions, the value of the ContextSensitiveHelpPage property will apply only to the controls that the
page extension adds to the extended page objects. For example, if your page extension adds two new controls to
the base application's Customer Card page, then the Learn more links in the tooltips for those two controls will
go to the Help page that you have specified. The Learn more links in the rest of the controls will go to the default
Help that is specified in the base application. This way, multiple apps can extend the same page object and each
apply their own content-sensitive Help link without overwriting the context-sensitive links for other apps.

NOTE
The app.json file also contains a help property that is used by AppSource to specify the link that describes the app or
solution.

UI-to-Help mapping for the base application


In the current version of Business Central, the context-sensitive links to Help for the base application is based on
a different UI-to-Help mapping that is stored in table 2000000198 Page Documentation . In this table, all page
objects in the default version of Business Central are listed, and have a target Help article associated with each
of them. Multiple page objects can be associated with the same Help article, such as when a specific workflow
involves multiple pages.
The base URL to the location of the target articles that are listed in table 2000000198 Page Documentation is
specified at the app level as /dynamics365/business-central/. In an extension, you can overrule this URL so that
all calls for Help go to your site instead. This is especially important for localization apps where all context-
sensitive Help calls for that app's language must go to the provider's website. For more information, see
Configuring the Help Experience.
Adding page -level UI -to -Help mapping to the system table
You can run a script that populates the Page Documentation table with a mapping for Microsoft's page objects
and your own page objects. This is useful if you want to reuse legacy Dynamics NAV Help for your Business
Central on-premises deployment.
Cau t i on

While it is possible to reuse the Dynamics NAV legacy Help with the legacy Dynamics NAV Help Server, and to
populate the system table, Page Documentation , we recommend that you convert any existing content to the
Business Central format, and that you fork our GitHub repos. For more information, see Extend and Collaborate
on the Help for Dynamics 365 Business Central and Migrate Legacy Help to the Dynamics 365 Business Central
Format.
In the following example, you have chosen not to apply context-sensitive Help links to your page objects and
instead you want to overwrite the UI-to-Help mapping that Microsoft has made in the system table.
Let's assume that the current mapping is:

PA GE ID PA GE N A M E REGIO N / C O UN T RY REL AT IVE PAT H

4 Payment Terms W1 sales-manage-sales

11300 Financial Journal BE how-to-create-financial-


journals

You want to replace the values of the fields in the Relative Path column with classic page-level Help files:
PA GE ID PA GE N A M E REGIO N / C O UN T RY REL AT IVE PAT H

4 Payment Terms W1 N_4

11300 Financial Journal BE N_11300

Once you have done this mapping, you can apply it to the Page Documentation table by using a script that
updates the table in the SQL Server database, for example.
You can find a couple of suggestions for how to go about this in our blog post, Reusing classic object-based Help
on your Dynamics 365 Business Central Help Server.

See also
User Assistance Model
Resources for Help and Support for Dynamics 365 Business Central
Adding Help Links from Pages, Reports, and XMLports
Migrate Legacy Help to the Business Central Format
Building Your First Sample Extension With Extension Objects, Install Code, and Upgrade Code
Building an Advanced Sample Extension
Development of a Localization Solution
JSON Files
Blog post: Extending and customizing the Help
Blog post: Collaborate on content for Business Central
Blog post: Reusing classic object-based Help on your Dynamics 365 Business Central Help Server
Docs Contributor Guide
Docs Authoring Pack for Visual Studio Code
Custom Help Toolkit
2/6/2023 • 2 minutes to read • Edit Online

Microsoft has published a GitHub repository with scripts and tools that can help you prepare customized Help
for your Business Central solution. This Help content can then be accessed from the user interface through the
Learn more links as described in Configure Context-Sensitive Help. You are welcome to use any tools or
processes to build and deploy content; this toolkit is intended to help you in some of the steps that are required.

TIP
You are not required to use the toolkit. It's available for you to use if it makes sense for your Business Central solution.

For example, if you deploy Business Central on-premises, you might want to set up a dedicated website with
customer-specific content that includes customized content from Microsoft. However, Microsoft's content is
optimized for the learn.microsoft.com site.
If your solution extends Business Central online with additional capabilities, we recommend that you set up a
website with your own content. To build the HTML files, use any third-party tool that you prefer, such as DocFX.
The GitHub repository includes source code for the tools, and we welcome contributions and feedback to
collaborate on improving the toolkit.

Tools in the toolkit


IMPORTANT
The HTMLFromRepoGenerator tool is being deprecated. To generate HTML files from Markdown, use another tool, such
as DocFX.
The language-specific repositories are also being deprecated, and will no longer be available at the end of the 2022
calendar year.

The toolkit is available at https://github.com/microsoft/dynamics365smb-custom-help. The repo contains the


following tools as well as the source code for the tools:
Dynamics NAV field Help conversion scripts
For more information, see Custom Help Toolkit: The FieldTopicTextExtractor tool

Custom Help
Depending on your solution, you are expected to deploy Help to a website that can be accessed by users of your
solution to supplement or replace Microsoft's content. For more information, see User Assistance Model and
Configuring the Help Experience. The toolkit is especially useful if you deploy a customer-specific solution that is
based on Microsoft's base application. If your solution extends Business Central online with additional
capabilities, we recommend that you set up a website with your own content. To build the HTML files, use any
third-party tool that you prefer, such as DocFX.
TIP
Microsoft's content in the various GitHub repos is optimized for the learn.microsoft.com site and the tools that are used
for this site. We encourage you to supplement our content with solution-specific content as opposed to attempting to
customize our content to fit your needs. But we acknowledge that there are situations when customizations are required,
and the toolkit's tools can help you achieve that.

See also
Configure Context-Sensitive Help
User Assistance Model
Migrate Legacy Help to the Dynamics 365 Business Central Format
Extend and Collaborate on the Help for Dynamics 365 Business Central
Custom Help Toolkit: The FieldTopicTextExtractor
tool
2/6/2023 • 2 minutes to read • Edit Online

If you are migrating a solution from Dynamics NAV to Business Central, you can use this tool to export the text
contained in the first paragraph of field-level Help topics for Microsoft Dynamics NAV 2018 or earlier versions.
You can then use these paragraphs as tooltip text in your Business Central solution.

NOTE
The tool does not import the tooltip text directly into your Business Central page objects. It creates a spreadsheet that
will make it easier to reuse the text from field-level Help topics in your Business Central solution.

Use the FieldTopicTextExtractor tool to extract content to Excel


Use the FieldTopicTextExtractor tool to populate an Excel workbook with the field IDs and the corresponding
first paragraph from a set of HTML topics from the Dynamics NAV field-level Help. The Dynamics NAV field
topics have a name in the format T_10_20.html for field 20 on table 10. The name of the resulting Excel
spreadsheet will be in the format Field_topic_summaries*.xlsx.
Here is the syntax for FieldTopicTextExtractor.exe:

FieldTopicTextExtractor.exe --n --o

Here is an explanation of the parameters:

PA RA M ET ER DESC RIP T IO N

n Specifies the path to the HTML files with Dynamics NAV field
topics.

o Specifies the path where the Excel spreadsheet must be


created.

Examples
The following example extracts the introductory paragraph from T_*.html files in D:\NAV to an Excel spreadsheet
with the name Field_topic_summaries*.xlsx in D:\BC:

FieldTopicTextExtractor.exe --n D:\NAV --o D:\BC

After extracting the Dynamics NAV field topic text


Excel makes it easy to bulk-apply and bulk-edit text strings because you can sort and filter data. If you work with
dedicated technical writers, then they are probably more efficient if they can work with tooltip text in Excel prior
to adding tooltip text to your Business Central solution. You can also take the opportunity to revise the text. For
more information, see Guidelines for tooltip text.
Before you import the tooltips into your solution, map the original field IDs to page control IDs in your Business
Central solution. It requires knowledge of the actual solution to determine which tooltips are relevant for which
pages, and Excel is very handy to help you in this process.
For example, the No field from the Customer table appears in several page objects. You can filter by the field
name, copy or tweak the text, and then map the relevant strings to the relevant page controls.

See also
Custom Help Toolkit
Migrate Legacy Help to the Business Central Format
Extend and Collaborate on the Help for Dynamics
365 Business Central
2/6/2023 • 18 minutes to read • Edit Online

The source files for the Help for the base application are available in public GitHub repos so that you can easily
extend and customize the content for your customers. In this section, you can learn about working with the
GitHub repos and Markdown files. You can also find guidance in the Learn Contributor Guide.

Get content from the GitHub repos


IMPORTANT
The HTMLFromRepoGenerator tool is being deprecated. To generate HTML files from Markdown, use another tool, such
as DocFX.
The language-specific repositories are also being deprecated, and will no longer be available at the end of the 2022
calendar year.

The dynamics365smb-docs and dynamics365smb-devitpro repos contain the source content in English (US).
When Microsoft publishes an update to the content, the main branch in the corresponding public GitHub repo is
updated. Typically, the source repo is updated weekly.

TIP
You do not have to get acquainted with GitHub if you just want to get the Microsoft content in HTML format to deploy
to a website, for example. You do not even have to get a GitHub account, as shown in the Getting by without GitHub
section. However, in many scenarios, you might want to join us in GitHub for closer collaboration and easier extensibility.

If you fork one of our repos, you can choose to update your fork with regular updates from the Microsoft repo.
The source repo, dynamics365smb-docs, contains packages of Markdown files for major versions and
snapshots of the docs for the previous minor version.
For example, go to https://github.com/MicrosoftDocs/dynamics365smb-docs/releases to get the release that
you need for your solution.
Guidance about what the Microsoft-provided content for Business Central is all about is available at User
Assistance Model.
The following table lists some of the key subjects that you should know about.

TO L EA RN M O RE A B O UT T H IS SUB JEC T GO TO T H IS SEC T IO N

Files and subfolders in the GitHub repos What the GitHub repos contain

How to interact with the GitHub repos Get updates from Microsoft

The mechanics of working in GitHub based on our internal Get started with GitHub
contributor guide
TO L EA RN M O RE A B O UT T H IS SUB JEC T GO TO T H IS SEC T IO N

How you can contribute to Microsoft's content Contributing

Forking a repo Get the content without a GitHub account

Generating content for your website Build HTML files

Potential problems you might have when you customize Known issues with Microsoft's content
Microsoft's content

Using the Dynamics 365 Translation Service to manage Translate the content
translations

What the GitHub repos contain


Microsoft's GitHub dynamics365smb-docs repos for Business Central Help contain the following folders:
archive
In the source repo only, this folder contains files that are not published but kept for backwards
compatibility use internally at Microsoft. You can ignore this folder. The folder does not exist in the
translation repos.
business-central
Contains Markdown files with content that is relevant for business users, administrators, and consultants
of Business Central
media-source
Contains source files for some of the pictures that are used in the Business Central content
templates
Contains three Markdown files that you can use as templates for your content. The templates define
required metadata and a recommended structure of the content.
The repos also contain files in the root of the repos that are used internally by Microsoft for managing the
content on the learn.microsoft.com site and by GitHub. They are not relevant for extending or customizing the
content.

TIP
The source repo, dynamics365smb-docs, contains packages of Markdown files for major versions and snapshots of the
docs for the previous minor version.
For example, go to https://github.com/MicrosoftDocs/dynamics365smb-docs/releases to get the release that you need
for your solution.

If you want to contribute to the developer and administration content, clone or fork the
https://github.com/MicrosoftDocs/dynamics365smb-devitpro-pb repo.

Get updates from Microsoft


Microsoft makes frequent changes to the Business Central content, and those changes show up in the public
GitHub repos. The base repo, MicrosoftDocs/dynamics365smb-docs, is updated weekly. When you decide it is
time to get the latest version of the content from Microsoft, you can do that using GitBash or GitHub Desktop.
The Help for GitHub offers an example of how this works in GitBash. In GitHub Desktop, just use the Merge into
current branch menu item to pull changes from the origin into your fork.
The following script was developed by a Danish partner to perform the following tasks:
Get the Microsoft source for a number of languages
Copy media files to the localization repos
Build HTML files
The script is provided in agreement with the partner without further support.

$languages = $("da-dk","de-ch","de-de")
$git = "C:\Program Files\Git\cmd\git.exe"
$docfx = "C:\GitHub\DocFx\docfx.exe"
$365docs = "C:\GitHub\MSFT\dynamics365smb-docs"
$langDir = "c:\Working\help\dynamics365smb-docs-pr."

Start-Process -FilePath $git -ArgumentList "clone --single-branch --branch main


https://github.com/MicrosoftDocs/dynamics365smb-docs.git" -WorkingDirectory "C:\working\help" -Wait
foreach ($language in $languages)
{
$arguments = $("clone --single-branch --branch main https://github.com/MicrosoftDocs/dynamics365smb-
docs-pr." + $language + ".git")
Start-Process -FilePath $git -ArgumentList $arguments -WorkingDirectory "C:\working\help" -Wait
Copy-Item $($365docs + "\business-central\docfx.json") $($langDir + $language + "\business-central")
Copy-Item $($365docs + "\business-central\media") $($langDir + $language + "\business-central") -Recurse
-Force
Copy-Item $($365docs + "\business-central\LocalFunctionality") $($langDir + $language + "\business-
central") -Recurse -Force
Copy-Item $($365docs + "\Templates") $($langDir + $language) -Recurse -Force
Set-Content -Path $($langDir + $language + "\business-central\docfx.json") -Value (get-content -Path
$($365docs + "\business-central\docfx.json"))
Start-Process -FilePath $docfx -ArgumentList $("C:\working\help\dynamics365smb-docs-pr." + $language +
"\business-central\docfx.json" + " --output c:\working\output\" + $language)
}

More information is available in the Build HTML files section.


Because the Microsoft repos are public, you do not need a valid GitHub account in order to get the content.
However, we recommend that, at a minimum, your organization has a system account with access to GitHub.
Get started with GitHub
To join Microsoft in the world of GitHub and Markdown, there are terminology and tools to get used to. The
following list outlines the main steps, but you can find additional content, tools, and ideas in the GitHub
documentation and other forums.
1. Fork the right repo.
You cannot work directly in the Business Central repos in the MicrosoftDocs GitHub org, such as the
dynamics365smb-docs repo. The first thing you need to do is create a fork of the repo under your GitHub
account. A fork is a copy of this repo that lets you work freely on the content without affecting the
MicrosoftDocs/dynamics365smb-docs repo.
Alternatively, you can clone the Microsoft repo. This is useful if you don't intend to customize Microsoft's
content, for example. But in many cases, forking the repo is more preferable.
Learn more at Set up your GitHub account and Set up Git repository locally for documentation in the
Docs Authoring Guide.
TIP
You are not required to make your GitHub repos public. When you fork a public repo, you can specify whether the
repo is public, private, or available only to specific GitHub accounts.

2. Install GitHub Desktop (optional) and clone your forked repo.


GitHub Desktop makes is easy to work and collaborate with repos locally from your own desktop. Learn
more at GitHub Desktop.
3. Get hold of your favorite Markdown editor, and start making changes.
The help content is stored in the business-central folder of the repo. Articles use a syntax for formatting
text called MarkDig Flavored Markdown, which is CommonMark compliant. To learn more about working
with Markdown, see Getting started with writing and formatting on GitHub.
If you want to work locally, you can edit using any text editor. Just save the file as a .md type. Here are two
good tools that provide you with some nice features, including a preview of how the content will be
rendered in HTML:
Visual Studio Code
Add the Docs Authoring Pack for Visual Studio Code, which gives you spell checker, Markdown
validation, and many other productivity features
Atom
Atom has spell check and is good for managing many files
Internally at Microsoft, some authors use Code, others use Atom, and for light-weight work, we tend to just edit
the content in the browser. You can find more guidance for how to get started with Markdown in the Docs
Contributor Guide. This guide is published by the team that built the learn.microsoft.com site where the Business
Central team publishes their docs.

Get the content without a GitHub account


If you do not want to collaborate with Microsoft on the content, you can get the latest version of the content
from GitHub without a GitHub account. For example, if you want content that is newer than the content on the
Business Central installation media, you can get the latest by simply downloading the content of the relevant
GitHub repo, which you can do without a GitHub account - the Microsoft repos are public so that anyone can
always get to them. Use a tool that can generate HTML files, create your own scripts, or follow this process to
fork a repo manually.
To get files without a GitHub account
1. Go to the relevant GitHub repo, such as this one: https://github.com/MicrosoftDocs/dynamics365smb-
docs/.
The browser will indicate when the content was last updated. Alternatively, go to the releases tab and
choose the package that you need for your solution. Learn more at What the GitHub repos contain.
2. Choose the green Code button, and then choose Download ZIP .
3. Open the downloaded dynamics365smb-docs-main.zip file and extract to a relevant location.
Now you have a copy of Microsoft's content. Next, you can generate HTML files for use on your website
as described in the Build HTML files section.
Build HTML files
For publishing to your own website, use any third-party tool that can clone a repo and generate the
corresponding HTML files.
Alternatively, you can create your own tooling and processes around DocFX, which is an open-source tool for
converting Markdown files. This section provides some guidance on how you can use DocFX to publish HTML
files from your fork of one of the Microsoft repos without using the HtmlFromRepoGenerator tool. You can find
additional tips in the Custom Help Toolkit article.

TIP
You can also use DocFX to generate content for the legacy Dynamics NAV Help Server. In that case, use the NAV
docfx.json file from dynamics365smb-docs.

1. Install DocFX on your computer.


DocFX is a command line tool, but you can also run it from a PowerShell script.
You must provide a .JSON file that defines certain build settings, including the output folder in which to
store the generated HTML files. We suggest that you use the docfx.json configuration file from the
dynamics365smb-docs repo. Learn more at Getting Started with DocFX.
2. To change settings in the docfx.json file, open the docfx.json file from the folder containing your local
clone in your preferred editor.
The following table describes key parameters for you to customize.

P RO P ERT Y DESC RIP T IO N

dest Specifies the output folder of the generated HTML files,


such as c:\Working\output\ .

template Specifies the templates that the HTML files will be


generated after. The default for Microsoft is blank, but
the value can be a string or an array.

globalMetadata Contains metadata that will be applied to every file, in


key-value pair format. You can also add other global
metadata, or metadata that applies to specific subfolders.

fileMetadata Contains metadata that will be applied to specific files,


based on the specified parameters, in key-value pair
format. The default is currently blank.

markdownEngineName Specifies the "flavor" of Markdown to use to build the


HTML files. The default is markdig .

Learn more at Properties for build section in the DocFx user manual.
The docfx.json files in the Microsoft repos have additional settings for the learn.microsoft.com site. If you
build the HTML files based on the docfx.json in the Microsoft repos, make sure that you have configured
it for your needs.
For example, in the globalMetadata section, set the ROBOTS property. We encourage you to use apply the
ROBOTS: NOINDEX, NOFOLLOW metadata to any customized versions of Microsoft's content. The intent is that
search engines will find Microsoft's original content on the learn.microsoft.com site rather than any
customizations that you and hundreds of other may have published. Set the metadata in the individual
files, or set it in the globalMeta section of docfx.json if you build using docfx.exe. For an example, see the
ui-work-with-notes.md file in GitHub, which we have deprecated but kept in the repo as an example.If you
use the docfx.json file to build HTML files for non-Microsoft functionality, then set the value of the
ROBOTS property when you build Microsoft's content. You can also add other global metadata, or
metadata that applies to specific subfolders.
3. Go to your desktop and open a command prompt.
4. Go to the docfx installation folder.
5. Run the equivalent of the following command:

docfx "c:\GitHub\MSFT\dynamics365smb-docs\business-central\docfx.json"

The files are generated as .html files and stored in the output location that is specified in the docfx.json file.

IMPORTANT
DocFx is no longer used internally in Microsoft and does not support YAML and other changes that we're making to our
content. Depending on the website that the HTML files will be deployed to, you might not be able to use the table of
contents file (TOC.html) that is generated in this process. That file is structured based on the configuration of the
https://learn.microsoft.com site. If you use the legacy Dynamics NAV Help Server, then you must use the ToC.xml file
instead.

The root of the MicrosoftDocs repos contain files that are related to internal Microsoft processes, such as
.openpublishing.build.ps1 . These scripts are used to validate and preview content, but they rely on internal
Microsoft resources that are not publicly available. The .openpublishing.redirection.json file lists files that were
published to the learn.microsoft.com site but have been deprecated later. As part of standard website practices,
the learn.microsoft.com site uses redirection to avoid broken links when a page is deleted, and the
.openpublishing.redirection.json file provides the mapping for redirection.

For inspiration for how to build your own help website, go to How-to: Customize DFM Engine in the DocFx user
manual and the Azure App Service documentation.
For tips and tricks about writing in Markdown, go to the Authoring Guide.
Links to anchors across languages
If your website supports two or more locales, you can use DocFx to generate HTML files for the relevant
languages. However, you may experience problems with links to anchors, also known as bookmarks.
For example, if your content has a link from article1.md to a specific section in article2.md, that link would be
formatted like this: [My translated subheading](article2.md#my-translated-subheading) . Then, when you run
DocFx to generate HTML files in Danish, DocFx will convert that link to
[Min oversatte overskrift](article2.md#min-oversatte-overskrift) . That is not a problem because the link will
work in both English and Danish.
But if you then want to use that link elsewhere, the link only works for one of the languages because the anchor
changed its name in the Danish translation. If you link to that subheading in article2 from your marketing site or
support site, or if you use it as the value of the ContextSensitiveHelpPage property, then it only works in English.
To work around this problem, we recommend that you create explicit anchors by tagging your subheading to
give it a fixed anchor. The following example illustrates how that would look in MarkDown:
### <a name="subheading"></a>My translated subheading

You would then be able to use the same link across all locales:
[My translated subheading](article2.md#subheading) , which would render in HTML as
myurl.com/docs/article2#subheading across all languages.

For more information, see Using hashtag in cross reference in the GitHub documentation.

NOTE
Adding fixed anchors is only relevant if you want to generate a link to a subheading that works consistently across
languages.

Alternatively, you can add a post-processing step to the script that you use to run DocFx to change the
equivalent of <h3 id=da-DK-anchor-name> with <h3 id=en-US-anchor-name> . In this example, the step would
change <h3 id=min-oversatte-overskrift'> to <h3 id=my-translated-subheading'> .

Known issues with Microsoft's content


Microsoft's content in the various GitHub repos is optimized for the learn.microsoft.com site and the tools that
are used for this site. It is not intended to be customized directly but to be supplemented by articles on your
local website. If you reuse Microsoft's content, you may experience a number of known issues, depending on
how you publish your content. This section describes recommended steps to work around these issues.
Docs are not available for a specific version
Microsoft's public GitHub repos reflect the latest version of Business Central. If you want to deploy help for an
earlier version of Business Central on-premises, then you can use the HTML files on the installation media. If you
find that that particular version is missing content, then please check the following sections for suggested
workarounds.
Broken links
If you deploy Microsoft's content to a website, your tools or your users will report that some links do not work.
The links result in a 404 error or similar. These errors are caused by Microsoft having deleted the target files due
to rework of the content. On the learn.microsoft.com site, we have tools that automatically handle links to
deleted files through redirection. But if you deploy Microsoft's content to your own website, you will not have
the same redirection.
We run periodic tests to catch these errors, but if you do see an error that is caused by a file not existing
anymore, check the .openpublishing.redirection.json file in the root of the source repo. This file is used by the
learn.microsoft.com site to manage redirection when a file is deprecated. For example, if you get an error that
"finance-how-to-set-up-sepa-direct-debit.md does not exist", then you can see in the
.openpublishing.redirection.json file that the article has been deprecated and replaced by finance-collect-
payments-with-sepa-direct-debit.md. You can replace the link in the file that is looking for finance-how-to-set-
up-sepa-direct-debit.md to link to finance-collect-payments-with-sepa-direct-debit.md instead.
ToC.xml for Help Server is different from the TOC.md file
Microsoft does not currently maintain the ToC.xml file and does not add new features to it. While the Help
Server component is still supported, it was deprecated in 2021 release wave 1. As a result, it contains links that
are broken, as described in the Broken links section.

Translate the content


You can use the Dynamics 365 Translation Service (DTS) to translate your own or the Microsoft-provided content
into other languages. The service is hosted in Lifecycle Services and currently supports translation of content in
Word documents and HTML files. Learn more at Translate documentation files.
To translate content for either Business Central or Dynamics NAV, choose Dynamics NAV as the product as
shown in the following illustration:

Contributing
A benefit of GitHub is the ability for you to contribute to the core content that the Microsoft team provides for
Business Central. There is a lot of good advice and best practices published in the Microsoft Docs contributor
guide. But this section provides information about how to apply that advice to the Business Central content.
We have two public GitHub repos that you can contribute to:
MicrosoftDocs/dynamics365smb-docs
This repo contains a copy of the source files for the business functionality content that publishes at
https://learn.microsoft.com/en-us/dynamics365/business-central

MicrosoftDocs/dynamics365smb-devitpro-pb
This repo contains a copy of the source files for the developer and admin content that publishes at
https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro

For example, you might have a new article that you think would be beneficial, or you might have a correction to
an existing article. If you would like to contribute to the Business Central content on the Microsoft Docs website,
you create a pull request from your repo to the target repo. The Microsoft team will then review the request and
include the changes as appropriate.
Get started
If you want to suggest a minor (or major) change to an existing article, follow these steps:
1. Find the published article, such as Using OData to Return or Obtain a JSON Document.
2. In the top right corner of the article, choose the Edit button.
Choosing the button takes you to the source file on GitHub. In this example, that's
https://github.com/MicrosoftDocs/dynamics365smb-devitpro/blob/main/dev-itpro/webservices/return-
obtain-json-document.md.

NOTE
If you're not already signed in with a GitHub account, you'll be prompted to sign in or create a new account. You
cannot contribute to the Business Central content without a GitHub account.

3. In the top right corner of the Markdown file, choose the pencil icon. Depending on who you are, you'll be
taken to a fork of Microsoft's repo, or you'll be able to work in a branch in Microsoft's repo.
4. Make the relevant changes (and remember to save the changes!).
5. Submit a pull request to the source repo.
You'll have something like this configuration in a browser:

Learn more at Quick edits to existing documents.


Get thorough
If you're going to contribute at a greater scale, for example as part of a community project that adds code
examples to a bunch of technical walkthroughs, you'll probably prefer to work locally on your device, based on a
clone of your fork. Go to Install content authoring tools in the Microsoft Docs Contributor Guide for
recommended tools and processes. The Microsoft team typically follows that workflow.
To create a pull request to the MicrosoftDocs/dynamics365smb-docs repo by using GitHub Desktop, do the
following:
1. Commit the changes to your fork that you want to include in the pull request.
2. Choose Sync to push the changes up to your repo on GitHub.
3. When the sync is completed, choose Pull Request , make sure that the pull request points at the
origin/main branch, and then choose Pull Request .
You'll have something like this configuration in a browser:
TIP
If you want to request brand new content, as opposed to contributing, we ask you to submit a request of type
Documentation at https://aka.ms/bcideas.

See also
Business Central User Assistance Model
Configuring the Help Experience
Custom Help Toolkit
Custom Help Toolkit: The FieldTopicTextExtractor tool
Authoring Guide
Docs Contributor Guide
Docs Authoring Pack for Visual Studio Code
Getting started with writing and formatting on GitHub
Visual Studio Code
Atom
DocFX
Blog post: Extending and customizing the Help
Blog post: Collaborate on content for Business Central
Authoring Guide for Dynamics 365 Business Central
2/6/2023 • 15 minutes to read • Edit Online

If you are contributing to the Business Central Help, or if you are customizing and extending the Microsoft
content for your own solution, you will probably want to use the same tools, processes, and style guide that
Microsoft uses.

Resources
The Microsoft Style Guide is published online
The content on the learn.microsoft.com site generally follows the Microsoft Style Guide. The content for
Business Central varies in certain ways, partly with product-specific terminology, and a generally more
conservative approach to contractions, for example. Also, since navigation in the Business Central user
interface is different from that of other Dynamics 365 apps, our guidance for steps that describe such
navigation is slightly different. For more information, see the Write for accessibility section.
Extend and Collaborate on the Help shows you the basics of collaborating on content for Business Central
The Docs Contributor Guide has many tips and tricks for authoring in MarkDown
The Docs Authoring Pack for Visual Studio Code adds productivity tools to Visual Studio Code

Write for accessibility


At Microsoft, we write for accessibility, which also means that the same content applies to interactions with the
software across devices, regardless of input method, for example. For more information, see Describing
interactions with UI in the Microsoft Style Guide. The product-specific guidance is found in the Navigation in the
product section.
Accessible illustrations
The accessibility requirements also impacts metadata for illustrations, such as the following:

:::image type="content" source="media/illustration.png" alt-text="Text used by screen readers.":::

Most of Microsoft's articles use a different MarkDown formatting for illustrations, such as the following:

![Lightbulb that opens the Tell Me feature.](media/ui-search/search_small.png "Tell me what you want to do")

Both formats are valid MarkDown, and both formats are supported by DocFx.exe. For more information, see
Images in the Docs Contributor Guide.
Navigation in the product
The Describing interactions with UI article in the Microsoft Style Guide also applies to Business Central content.
However, the navigation in Business Central is very different from many other Microsoft products, and users can
even pin actions and personalize their workspace in other ways that change the navigation path.
As a result, we often choose to be not very specific about how to find a given action. We write Choose the
Register Payments action, rather than try to predict if the user will find that action pinned to their action bar or
hidden away under More options , for example.
But we also have written something like this: To map text on the vendor invoice to a specific debit account, on
the Actions tab, in the General group, choose Map Text to Account, and then fill the Text-to-Account Mapping
Worksheet page.. In this example, the guidance is now outdated - the actual action is, in the default configuration
of the CRONUS demonstration company, easily discoverable in the Process part of the action bar, which is the
first place people tend to look for things. In other words, the instructions Choose the Map Text to Account action
would have made it easier for users to find the action.
The following table provides examples of how to write about the user interface in a helpful but futureproof way,
with accessibility in mind.

PA GE T Y P E EXA M P L E DESC RIP T IO N

List On the Oppor tunity List page, Most list pages have relatively few
select the opportunity, and then actions, so let's keep things simple.
choose the Assign Sales Quote Also, most actions in the action bar for
action. list pages apply to the line entry that
you have selected.

Card On the General FastTab, in the Cards can have several FastTabs that
External Document No. field, enter each have multiple fields. Telling the
the invoice number. user to find a certain field on a specific
FastTab can save time.

Card On the Customer Card page, choose This type of action is relatively easy to
the Merge With action. find in the Actions part of the action
bar.

Document On the Lines FastTab, in the Item No. Documents, such as sales orders, have
field, enter the number of an inventory a header section and a lines section,
item or service. typically. So letting the user know
which section the field is in can save
time.

Authoring in MarkDown
The Business Central content is styled using a MarkDown syntax as described below. Extended guidance is
available in the MarkDown Reference section in the Docs Contributor Guide.
Headings
Use # for headings. For more information, see Headings in the Docs Contributor Guide.
In the source files for the Business Central content, which publishes as English (US) on the learn.microsoft.com
site, the title of an article is expected to use Title Case (capitalize each word, except prepositions) whereas
subsequent headings use Sentence case (capitalize the first word, only). The Microsoft Style Guide recommends
a different approach.
Metadata

The content on the learn.microsoft.com site includes metadata that is used by the site and feeds our internal
telemetry dashboards. The metadata is required for Microsoft's content but not necessarily for content that
extends or customizes Microsoft's content.
However, some metadata is recommended as a best practice as outlined in the following table.
M ETA DATA TA G DESC RIP T IO N

title Used by search engines. Recommended length of 60-70


characters, including spaces. We recommend that the title
metadata is the same as the first heading in the article.

description Used by search engines. Recommended length of 100-160


characters, including spaces.

author GitHub account of the main contributor to the article.

ROBOTS Please apply this tag if you customize one of Microsoft's


articles and deploy that to your website. By applying the
metadata ROBOTS: NOINDEX, NOFOLLOW , you help make
sure that search engines will find the original article rather
than your customized version. Users of your Help will still be
able to find the customized article through context-sensitive
Help links and other links.

Bulleted lists
Use - or * to create bullets as shown in the following example:

The following options are available:

- first option
- second option
- third option

TIP
It doesn't matter if you use - or * , but the current version of the Docs Authoring Pack requires each article to use one
or the other and not mix them up.

As a best practice, the MarkDown validation in the current version of the Docs Authoring Pack recommends a
blank line between options in a bulleted list for better readability in MarkDown.
Ordered lists
Use numbers for ordered lists. Do not add spaces between the lines.

1. Choose the ![Lightbulb that opens the Tell Me feature.](media/ui-search/search_small.png "Tell me what
you want to do") icon, enter **Payment Journal**, and then choose the related link.
2. In the **Payment Journal** window, on the first journal line, enter the relevant information about the
payment entry.
3. To apply a single vendor ledger entry:
4. In the **Applies-to Doc. No.** field, choose the field to open the **Apply Vendor Entries** window.

Bold and italics syntax


Use **bold** and *italics*
Tables
For tables in the body, use the markdown syntax. The Docs Authoring Pack for Visual Studio Code has a shortcut
for adding a table, and you can also use Tables Generator.
| To | See |
|------|---------------------------|
|<text>|<link>|
| | |
| | |

MarkDown syntax for nested tables is limited, so we recommend using HTML-syntax for nested tables in
ordered and unordered lists use HTML-syntax.
Placeholders
Rather than repeating text in two or more articles, use includes. For more information, see Included Markdown
files.
For Business Central, we use includes for boilerplate text, for content that is repeated in more than one article,
and for the product name. That way, we can make changes in just one location - and so can you.

TIP
In the dynamics365smb-docs repo, the includes are in the business-central\includes subfolder.
In December 2020, the two placeholders for the product name, prodshort.md and prodlong.md, were renamed to
prod_short.md and prod_long.md. The change solved a problem internally at Microsoft, because we have a tool that helps
identify spelling error, and that tool generated warnings for prodshort.md and prodlong.md.

Comment syntax
Useful for sections that are not ready and will not pass build checks.

<!-- Comments -->

Examples:

<!-- [Managing Payables](payables-manage-payables.md)-->


<!-- This is a paragraph that spans more lines and I can just put the comment tag
at the beginning and end of it -->

Links
Ordinary link to a different topic in the same folder
These links have the format [link text](filename.md) .
Example: [Managing Payables](payables-manage-payables.md)

Link to a topic in a subfolder of the source topic


These links have the format [link text](subfolder/filename.md) .
For example, you want to link to payables-manage-payables.md from ui-work-general-journals.md, where the
folder structure is as follows:
articles
ui-work-general-journals.md
ManagePayables
payables-manage-payables.md
Here is the link: [Manage Payables](ManagePayables/payables-manage-payables.md)
Link to a topic in a different folder than source topic
These links have the format [link text](../folder/filename.md) .
For example, you want to link to payables-manage-payables.md from receivables-manage-receivables.md,
where the folder structure is as follows:
articles
ManageReceivables
receivables-manage-receivables.md
ui-work-general-journals.md
ManagePayables
payables-manage-payables.md
Here is the link: [Manage Payables](../ManagePayables/payables-manage-payables.md)

Link to a place in the same article


From within an article, you can create a link to a specific heading in the same article. You can create the link like
other links except with the following format:
[link text](#target-heading)

target-heading is the text of the heading that you want to link to, except it is all lowercase and spaces between
words are replaced with hyphens. For example, here is the link:
[How Autoscaling Works](#how-autoscaling-works)

To the heading: ## How Autoscaling Works

Link to a place in a different article


From an article, you can create a link to a specific heading in another article. You can create the link like other
links except with the following format:
[link text](targetarticlename#target-heading)

targetarticlename is the file name of the article, including the .md file type. target-heading is the text of the
heading that you want to link to, except it is all lowercase and spaces between words are replaced with hyphens.
For example, to link to the heading "How autoscaling works" in the article Autoscaling.md, add the following
code: [How autoscaling works](Autoscaling.md#how-autoscaling-works)
Links to anchors across languages
If your website supports two or more locales, you can use DocFx to generate HTML files for the relevant
languages. However, you may experience problems with links to anchors, also known as bookmarks.
For example, if your content has a link from article1.md to a specific section in article2.md, that link would be
formatted like this: [My translated subheading](article2.md#my-translated-subheading) . Then, when you run
DocFx to generate HTML files in Danish, DocFx will convert that link to
[Min oversatte overskrift](article2.md#min-oversatte-overskrift) . That is not a problem because the link will
work in both English and Danish.
But if you then want to use that link elsewhere, the link only works for one of the languages because the anchor
changed its name in the Danish translation. If you link to that subheading in article2 from your marketing site or
support site, or if you use it as the value of the ContextSensitiveHelpPage property, then it only works in English.
To work around this problem, we recommend that you create explicit anchors by tagging your subheading to
give it a fixed anchor. The following example illustrates how that would look in MarkDown:
### <a name="subheading"></a>My translated subheading

You would then be able to use the same link across all locales:
[My translated subheading](article2.md#subheading) , which would render in HTML as
myurl.com/docs/article2#subheading across all languages.

For more information, see Using hashtag in cross reference in the GitHub documentation.

NOTE
Adding fixed anchors is only relevant if you want to generate a link to a subheading that works consistently across
languages.

Line breaks (soft return)


In the editor, add two blank spaces at the end of the sentence and hit return. This is used in the See Also list. (See
Also must be heading 2.)
Continue steps after a non-step para
Enter four spaces in front of the non-step para. Otherwise, the non-step para will restart the step sequence.
TOC
The TOC structure of the TOC.md file is as follows:

#[Overview](overview.md)
##[Topic 1](topic-1.md)
##[Topic 2](topic-2.md)
##[Topic 3](topic-3.md)
##[Topic 4](topic-4.md)

Standard phrases
All fields in Business Central have tooltips; therefore, do not document fields in Help. To refer readers to the
tooltips, use this standard phrase where relevant:

"Choose a field to read a short description of the field or link to more information."

For more information, see Business Central User Assistance Model.


Recycle content
Rather than copy-pasting content that you want to surface in two or more places, use includes. For more
information, see Included Markdown files in the Docs Contributor Guide.
Topic titles
Use imperative verb form for step-based topics ("Pay vendors").
Use gerund verb form for conceptual, non-step topics. ("Paying Vendors")
Use nouns for highest-level topics. ("Sales")
File naming
In this section, we describe best practices for file names of MarkDown files that will publish to a website. The
guidelines make the files easier to work with and better for search engines to index.
Rules
No spaces or punctuation characters. Use hyphens to separate the words in the file name.
Use all lowercase letters
No more than 80 characters - this is a publishing system limit
Use action verbs that are specific such as develop, buy, build, troubleshoot. No -ing words.
No small words - don't include a, and, the, in, or, etc.
All files must be in markdown and use the .md file extension.
New FAQ files must use YAML format. For an example, see the
https://github.com/MicrosoftDocs/dynamics365smb-docs/blob/live/business-central/faq-copy-paste.yml file.
Examples of file names

TO P IC T IT L E N A M IN G

Select a Company ui-how-select-company.md

Enter Criteria in Filters ui-enter-criteria-filters.md

Troubleshooting: Record Locked by Another User ui-troubleshoot-record-locked-another-user.md

Changing Basic Settings ui-change-basic-settings.md

Sales sales-manage-sales.md

Set Up Currencies finance-setup-currencies.md

Set Up Purchasers purchases-how-setup-purchasers.md

Understanding Session Timeouts admin-understand-session-timeouts.md

Manage Data Encryption admin-manage-data-encryption.md

Country-specific content
To simplify content localization and translation, country-specific articles live in country-specific folders. The TOC
entries live under the "Local Functionality" parent node.

User interface text


If you're a technical writer, then you're likely to either write or edit user interface text, such as captions, warnings
and error messages, tooltips, and teaching tips. In this section, we describe our internal guidance, but you can
choose differently.
Tooltips
The Microsoft user assistance model requires a tooltip for all controls of type Action and Field that exist on page
objects. Follow these guidelines:
If the control is a field, begin with the verb Specifies.
If the control is an action, begin with a verb in the imperative form , such as Calculate or View .
Include the most valuable information that users need to perform the task(s) that the field or action
supports.
For example, for the Post action, do not write Post the document. Write, for example, Update ledgers with
the amounts and quantities on the document or journal lines.
Describe complex options in tooltips for option fields.
Use a colon to call out the option name and its description. See example 3 below.
Try to not exceed 200 characters including spaces.
This makes the tooltip easier to scan so the user can get unblocked quickly. However, the UI will render
longer tooltip text if you want to provide more detailed user assistance.
Do not use line breaks in the tooltip text.
The tooltip cannot render formatting or line breaks.
Examples of tooltips
The following table shows examples of effective tooltips.

C O N T RO L N A M E TO O LT IP

Password field Specifies your company's password to the service that


converts bank data. The password that you enter in this field
must be the same as on the service provider's sign-on page.
(175 characters including spaces)

Entries action View the history of transactions that have been posted for
the customer.
(72 characters including spaces)

Account Type field Specifies the purpose of the account. Total: Used to total a
series of balances on accounts from many different account
groupings. To use Total, leave this field blank. Begin-Total: A
marker for the beginning of a series of accounts to be
totaled that ends with an End-Total account. End-Total: A
total of a series of accounts that starts with the preceding
Begin-Total account. The total is defined in the Totaling field.
(522 characters including spaces)

Errors, warnings, and other messages


Messages that users see when they work in Business Central, some as confirmations, others as warnings, for
example, are defined in code. In this section, we describe key things to keep in mind when writing or editing this
type of user interface text.
Be brief but descriptive with clear call to action.
Especially true for errors and warnings that must help the user unblock themselves.
Write to be understood worldwide.
Write content that's easy to read and translate.
Avoid long, complex sentences. Break them up into shorter sentences that are easier to read and
comprehend.
Use lists and tables instead of complicated sentences and paragraphs.
Use standard English grammar. In particular, avoid incomplete sentences.
Include words that native English speakers often omit, such as that and the.
Only use placeholders for variables and field values where the result depends on context.
Write out all static captions, where the value is always known.
All placeholders complicate translation, also valid ones, even when they are preceded by code comments.
A typical challenge is to determine the gender of the noun that a placeholder represents. This is
problematic for target languages such as French, German, and Russian.

USE IN ST EA D O F

The document has been posted. The %1 has been posted. (Translators cannot determine
the gender.)

The Unit Cost field is updated. The %1 field is updated. (Where %1 always represents
"Unit Cost".)

Document %1 contains invalid characters. (Where %1


represents a given document ID.)

Option %1 is not supported. (Where %1 represents one


of more options.)

Do not place quotation marks around placeholders.


However, if the placeholder represents free-text user input that is hard to distinguish, such as a payment
comment on a bank transaction. The quotation marks then helps to distinguish the user input from other
parts of the message.
Example: The payment line with transaction text '%1' is not applied., where %1 =
Hi - here is my payment of invoice 1223344 .

Teaching tips
APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

2021 release wave 1 brought an interpretation of teaching tips that you can add to your Business Central
solution. Use the teaching tips from the onboarding framework to introduce users to complex pages, and to
build tours that help users understand the purpose of a complicated area, for example. Create the teaching tips
in code by setting the AboutTitle and AboutText properties.

See also
Business Central User Assistance Model
Extend and Collaborate on the Help
Configuring the Help Experience
Docs Contributor Guide
Docs Authoring Pack for Visual Studio Code
Getting started with writing and formatting on GitHub
Visual Studio Code
Atom
DocFx
Blog post: Extending and customizing the Help
Blog post: Collaborate on content for Business Central
Migrate Legacy Help to the Dynamics 365 Business
Central Format
2/6/2023 • 5 minutes to read • Edit Online

If you are building an app for Business Central, we expect you to comply with the user assistance model. That
means that tooltips and callouts explain all fields and actions, and conceptual descriptions of functionality are
published to a website. Fortunately, there are many ways in which you can migrate and reuse your existing Help
within this model.

Reusing existing web content


You can reuse your existing product Help solution in most situations. If the content is already published to an
internal or external website, all you have to do is to add that online library to the configuration of Business
Central online or on-premises. For more information, see Configuring the Help Experience.
More specifically, if you have content for Dynamics NAV, then you can choose to reuse that content for your
Business Central solution.
For example, you have a Dynamics NAV Help Server website with HTML files that describe your solution
according to the Microsoft Dynamics NAV 2013 R2 documentation model and format. You decide to reuse the
Help Server website and rebrand the website and the content. Finally, you connect your Business Central
solution with the Help Server website. For more information, see Configuring the Help Experience.
Business Central does not support the field-based approach to context-sensitive Help that Dynamics NAV 2017
and earlier versions use. Instead, you must use the Business Central page-based approach to context-sensitive
Help. You do not have to convert your existing Help, but you do need to make the content available. For more
information, see the Converting existing content section.

NOTE
For apps for Business Central online, you must apply tooltips to controls and actions in both page objects and page
extensions, and you must supply context-sensitive links. For more information, see Configuring the Help Experience.

Converting existing content


Your existing content might be in a different format, such as PDF files, Word documents, or printed manuals. You
must decide if you want to keep the content as-is, or if you want to convert it to a format that can be accessed
from inside Business Central. There are third-party tools available that can help you migrate your content,
depending on the current format and the target format.
In this example, you are migrating your solution from Dynamics GP, and you have content in PDF files. You
choose to convert the content to MarkDown as described in the Moving to MarkDown section. Then, you
publish to a new online library on your current website. Sounds too easy? Well, it doesn't have to be more
complicated, and it's a one-off project.
Migrating from Dynamics NAV
If you are migrating your solution from Microsoft Dynamics NAV 2013 R2, Microsoft Dynamics NAV 2017, or a
version in between, then you most likely have been using the Dynamics NAV Help Server, and your Help content
is in HTML format. That means that you have a free choice of what to do:
Reuse your existing content as-is but redeployed to a new website
Use a third-party solution to convert some or all of your HTML files to MarkDown if you want to follow
similar processes to the ones the Microsoft team follows
For more information, see the Moving to MarkDown section.
If you are migrating from an earlier version of Dynamics NAV, then you can choose to first migrate to the
Microsoft Dynamics NAV 2013 R2 format, and then migrate again to MarkDown. For more information, see
Upgrading Your Existing Help Content in the legacy docs for Microsoft Dynamics NAV 2013 R2.
Converting legacy Dynamics NAV field Help to tooltips
Tooltips play an important role as part of the Business Central user assistance model, and we encourage you to
apply tooltips to your controls and actions as well.
You can reuse text from your Dynamics NAV Help for table fields: The FieldTopicTextExtractor tool can extract the
first paragraph from your Dynamics NAV Help topics for table fields. The resulting spreadsheet will help you
copy and paste the text from your Dynamics NAV Help topics into the ToolTip property of your controls.
Mapping the table fields to page controls is not always straightforward. Because the same table is often used by
two or more pages, the page ID can be many numbers away from the table ID. It requires knowledge of the
actual solution to determine which tooltips are relevant for which pages. The FieldTopicTextExtractor tool
generates an Excel file that you can use for this purpose. At Microsoft, we went through a similar process when
we converted our field Help into tooltips. We find Excel useful because you can sort and filter, and then copy
content to other fields, for example.
In the base application, tooltips are in the page objects, so we edit code to edit tooltips. You do not have to do
the same. You can choose to work with tooltips in the translation files or straight in code. Different solutions
require different processes, so pick the process that is more efficient for you.
We chose to associate the "What is this field?"-content with the user interface, meaning the controls on page
objects. In the Dynamics NAV Help model, we chose a different approach, focusing on the database structure.
Both approaches have their advantages and disadvantages, but the Business Central user assistance model
currently focuses on the user interface with tooltips on page objects. For more information, see User Assistance
Model.
For more information, see the following articles:
Working with Application Objects as Text Files in the docs for Microsoft Dynamics NAV 2016
How to Add Translated Strings By Importing and Exporting Multilanguage Files in the docs for Microsoft
Dynamics NAV 2018
Working with Translation Files for Business Central

Moving to MarkDown
Converting your existing content to MarkDown can be done using third-party tools, including but not limited to
PanDoc or the Writage plugin for Word.
Once you have converted your content to MarkDown, we recommend storing your content in a repository from
where you can publish to your website, such as the following:
A Git repo in Azure DevOps
A private or public repo in GitHub
A project in MkDocs
Use open-source tools such as DocFx to generate content for your website. By working in MarkDown, you have
access to a world of open-source tools.
If you do not yet have a website that you publish content to, then there are several ways in which you can create
such a site. For example, the MkDocs project generates a website for you. You can also work with a web designer
to build a site to host your content. We recommend deploying to an Azure web app. Business Central does not
require a special design of your website, unlike the now deprecated Dynamics NAV Help Server. It's your choice
what the website looks like, including the styling.

See Also
Configuring the Help Experience
Extend and Collaborate on the Help
User Assistance Model
Development of a Localization Solution
System Requirements
Administration of Business Central Online
2/6/2023 • 11 minutes to read • Edit Online

Administrators that can manage Business Central online tenants are either an internal administrator, who is an
employee of the company that bought the Business Central subscription, or an administrator from the reselling
partner company. Some of the tools are the same, and some tools are available to partners only. Here you can
learn which tools are available to you as an administrator.

Administration as an internal administrator


Internal administrators are the system administrators, IT professionals, or superusers of the customer's
company, who are assigned the Global admin role in the Microsoft 365 admin center. For more information,
see About admin roles in the Microsoft 365 admin content.
Administration in Business Central
As the internal administrator, you can add users and grant permissions. For more information, see Create Users
According to Licenses and Assign Permissions to Users and Groups in the business functionality content for
Business Central.
As an internal administrator you have read-only access to all areas of Business Central. You will have this
access even if your organization decides not to continue with Business Central and cancels the subscription. That
way, the internal administrator can export relevant data, while no one else in the organization has a license to
sign in and use Business Central.

IMPORTANT
You must have a Business Central license in order to set up integration to other products, or perform any other tasks in
Business Central, except the two mentioned above. For information about licensing, see Microsoft Dynamics 365 Business
Central Licencing Guide.

For other tasks, you can access the Business Central administration center, where you can manage upgrade
schedules and other tasks. For more information, see The Business Central Administration Center.
You can also use telemetry to track usage and monitor user sessions, for example. For more information, see
Monitoring and Analyzing Telemetry and Managing Sessions.
Administration of a trial
If your organization has signed up for a Business Central trial, you can extend the free trial, and you can start the
process of finding a reselling partner to help you get a subscription. For more information, see Dynamics 365
Business Central Trials and Subscriptions.
Administration in the Microsoft 365 admin center
The Global admin role makes you an administrator of your organization's Microsoft 365 tenant. This role
means that you can manage the subscription, add or remove users, and assign or remove licenses in the
Microsoft 365 admin center. For more information, see Microsoft 365 Admin help center.
Collaboration with reselling partners
When your organization subscribes to Business Central, you have a relationship with an authorized partner of
Microsoft. The partner company assists with licensing, configuration, and other tasks. They can also help you get
telemetry about your Business Central environment.
The partner will have access to your tenant as a delegated administrator. You can configure their access to your
data. Starting in February 2022, the partner can request granular delegated admin privileges, and we
recommend that you work with your partner or partners to change their access to your tenant to use the
Dynamics 365 administrator role rather than the Global admin role. For more information, see Managing
delegated permissions as an internal administrator.
If your organization decides to switch to another partner, you must take the following steps:
1. Ask your current partner to remove the reseller relationship with you in the Partner Center
2. Remove their delegated administration privileges
a. In the Microsoft 365 admin center, under Settings , choose Par tner relationships , and then select
the partner of interest
b. In the details pane, choose Remove delegated admin
c. In the confirmation pane, choose Remove
d. Disable their user accounts in Business Central
3. Remove any settings in the Business Central administration center if the partner did not already clear
their settings.
For more information, see Internal administrators.
4. Add your new partner to your subscription, and work with them to get them set up
Unsubscribing from Business Central
If the organization decides not to continue with Business Central, you can then cancel the subscription.
In the Microsoft 365 admin portal, you can remove licenses from users. As the administrator, you can remove a
trial subscription from your company's account. But to cancel a paid subscription, you must contact your
reselling partner, and they can cancel the relevant subscription in the Partner Center. For more information, see
the Data and access when a trial or subscription ends section.

Administration as a partner
As a Business Central reselling partner, you are the administrator of the Business Central tenants of your
customers. You have access to the administration tools of their Microsoft 365 account and their Business Central
administration center where you can specify update windows. You can also log into their Business Central as a
delegated administrator if you want to reproduce errors.
Join the Microsoft Partner Network
Microsoft Partner Network (MPN) membership unlocks our best resources to differentiate your business, take
your product to market, and sell your solutions. To become a partner, you must join the Microsoft Partner
Network (MPN), at which time you will be assigned an MPN ID. MPN membership is free to all partners; you can
enroll in the MPN here.
Once signed up, you will get an MPN ID – your gateway to access all the membership resources and benefits for
your partnership with Microsoft. There is no cost to obtain a MPN ID as a Network member, and with options to
upgrade to an Action Pack subscription or work toward a competency, you can access even more benefits.
Set up your Partner Center account
Once you have joined the Microsoft Partner Network (MPN), you can set up your Partner Center (PC) account.
The Microsoft Partner Center is a generic portal where partners can sell and manage customer subscriptions for
Microsoft services, such as Microsoft 365, Azure, Dynamics 365, and others, as well as for some third-party
products. For more information, see the Partner Center documentation.
Your Partner Center account provides you with access to pricing information, tools and services, and enables
you to manage admin credentials for your company's work account. Partner Center is also where you can
purchase or renew subscriptions to Microsoft Action Packs, create a business profile to receive and manage
sales leads from Microsoft, and see if you qualify for co-selling opportunities.
Enroll in the CSP program
The Cloud Solution Provider (CSP) program helps your company to be more involved in your customers'
businesses, beyond reselling licenses. In CSP, you can choose to enroll as an indirect reseller or a direct bill
partner.
In most cases, you will enroll as an indirect reseller and then work with an indirect provider, also referred to as a
distributor, who then manages all interaction with Microsoft in terms of licensing and technology, so that you
can focus on sales and support. If you decide to enroll as a direct bill partner in order to fully own the end-to-
end relationship with both customers and Microsoft, make sure that you meet the eligibility requirements. For
more information, see Enroll in the Cloud Solution Provider program in the Microsoft Partner Center content.
The Microsoft Partner Center is a generic portal where partners can sell and manage customer subscriptions for
Microsoft services, such as Microsoft 365, Azure, Dynamics 365, and others, as well as for some third-party
products. For more information, see the Partner Center documentation.
Some indirect providers (distributors) provide their resellers with a custom portal that optimizes and enhances
the experience beyond the Partner Center. They can also provide indirect resellers with an API to automate some
of the customer onboarding steps. Contact your indirect provider to find out more.
Both indirect resellers and direct bill partners can access and support their customers' Business Central by
setting up a reseller relationship with them.
To service customers in a specific country, your partner company's Azure Active Directory (Azure AD) tenant and
CSP account must be registered in the regional CSP market that covers that country. For more information, see
Cloud Solution Provider program regional markets and currencies.

NOTE
When you buy Business Central offers on behalf of your CSP customers, the CSP offer must be available in both your own
tenant's country and in your customer's tenant's country. For example, if your tenant is located in Slovakia and the
customer's tenant is in Germany, you will not be able to sell Dynamics 365 Business Central Premium to that customer,
because this offer is currently not available in Slovakia.
Similarly, if your tenant is located in Germany and the customer's tenant is in Slovakia, you will not be able to sell
Dynamics 365 Business Central Premium to that customer, because this offer is currently not available in Slovakia.

In the Microsoft Partner Center documentation, you can learn how to request a reseller relationship with
customers, assign licenses to users, and create new subscriptions. Business Central is one of the subscriptions
that you can create, and there are Business Central-specific license types that you can assign to users.
You must also assign certain roles to users in your own organization so that they can support your customers.
Add users from your own organization
In most cases, your partner company includes employees with different responsibilities, and you can assign
different roles depending on people's responsibility. This way, you can be very explicit about who from your staff
can access your customers' data, for example.
For each user, you can assign permissions for 2 categories of tasks:
Managing your organization's account
This controls access to the functionality of the Partner Center portal
Assisting your customers
This controls access to your customers' environments
When you establish a reseller relationship with a customer in Partner Center, you must specify which people
from your organization will assist that customer's tenant as either Admin agent or Helpdesk agent. These users
can manage implementation, support, and troubleshooting tasks for your customers. Once the reseller
relationship with a customer is established, they will be able to login into the Business Central environments of
the customer without a license. The number of partner users that can access customer environments is not
restricted.
This way of accessing customer resources is called delegated administration, and the partner users are therefore
called delegated administrators or delegated admins in daily shorthand. For more information, see Delegated
Administrator Access to Business Central Online.
Since February 2022, you can set up security groups with granular delegated admin privileges to better control
who has access to which customers with which level of access to the customer's Business Central environment.
This way, the delegated admins no longer have to be global admins for the customer's Active Directory. For
more information, see the Delegated Administrator Access to Business Central Online section, and also the
Admin roles article in the Microsoft 365 admin content.

NOTE
These users cannot provide accounting services for the customers. For this purpose, the customers must use the
External Accountant license, which is also available via CSP.

Connect with customers


As a CSP partner, you can manage a customer's subscriptions and services on their behalf in the Partner Center
by establishing a reseller relationship with your customers. If they already have an account, such as if they
currently use Microsoft 365, other Dynamics 365 apps, or PowerApps, for example, you can send them an
invitation straight from the Partner Center. For more information, see Connect with customers in Partner Center
(indirect providers/distributors) and Connect with customers (indirect resellers).
When the customer's internal administrator receives the invitation link and navigates to it, they must
acknowledge that they have read the Microsoft Customer Agreement and that they can authorize you as their
reseller on behalf of their organization. For more information, see Confirm customer acceptance of the
Microsoft Customer Agreement.
When a customer accept this reseller relationship, delegated administration privileges must be set up . For more
information, see Delegated Administrator Access to Business Central Online.
If you are working as an indirect reseller, your indirect provider (distributor) must associate your customers with
you in their Partner Center.
Acting as a delegated administrator
As a reselling partner, you have delegated administration access to their Business Central and other services. For
more information, see Delegated Administrator Access to Business Central Online.
Manage technical support
As a reselling partner, you must be the first line of support for your Business Central customers. Set up your
support contact information, and help the internal administrators troubleshoot any issues that users find. For
more information, see Managing Technical Support.

Trials
Organizations can sign up for different types of trials, and some trials can be extended. For more information,
see Trials and Subscriptions.
Data and access when a trial or subscription ends
Trials can expire, and so can a paid subscription, such as if the organization does not renew the subscription,
stops payments, or if they cancel the subscription.
When a subscription expires, two special periods kick in:
Grace period
Data retention period
The grace period is a period of 30 days when the customer can still access the product without any restrictions.
After the grace period, the subscription enters the data retention period, which is another 90 days during which
only the admin users of the Azure Active Directory tenant can login into the product. After those 90 days,
Microsoft deletes the data automatically.
This policy is general across Microsoft's online offerings, as you can see in this example from Microsoft 365:
What happens to my data and access when my Microsoft 365 for business subscription ends?.
The same applies to trials that are based on the Dynamics 365 Business Central Premium Trial license. But
this does not apply to viral trials.

Understanding Business Central online infrastructure


If you are migrating from an on-premises solution, understanding the infrastructure of Business Central online
can help you make good choices for how to set up environments and companies. For more information and an
example, see Understanding the infrastructure of Business Central online.

See Also
The Business Central Administration Center
The Business Central Administration Center API
Submitting support requests on behalf of your customer
Resources for Help and Support for Dynamics 365 Business Central
How does Microsoft handle database sizes?
Version numbers in Business Central
Get Started as a Reseller of Business Central Online
Deliver consulting services as a VAR: aka.ms/BusinessCentralConsultingServices
Monitoring and Analyzing Telemetry
Trials and Subscriptions
Understanding the infrastructure of Business Central online
Understanding the Infrastructure of Business Central
Online
2/6/2023 • 5 minutes to read • Edit Online

When someone wants to buy Business Central online, a couple of questions must be answered because
Business Central can be configured along several different axes. In this section, we describe the topology of
Business Central online so that you can make qualified decisions for how a Business Central tenant will be
deployed and configured.

TIP
Business Central is available in a limited number of markets. For more information, see Country/regional availability and
supported languages. For a visual overview of where Business Central online is deployed, see the Geographical availability
site.

Microsoft 365 and Azure Active Directory


The first decision to make is related to the Azure Active Directory (Azure AD) tenant that is required to use for
Business Central online. To sign up for a trial, use a work or school account. For more information, see Try or buy
a Microsoft 365 for business subscription.
This account is an important step because it is tied to a region of the world. Users are defined in the Azure AD
account and then assigned the relevant licenses in the Microsoft 365 admin center. It is also important for the
reseller's Azure AD. For more information, see the Enroll in the CSP program section.

TIP
For some customers, the right approach is to have multiple Azure AD tenants due to their own organizational structure.
However, in Business Central, all users of an environment must belong to the same Azure AD tenant.

If an organization's structure changes over time, admins can transfer environments from one Azure AD tenant to
another. For more information, see Move an Environment to another Azure Active Directory organization.

Environments and companies


Each Azure AD tenant that buys a Business Central online license automatically gets some environments. Each
environment is tied to a specific country and localization.

NOTE
The Premium and Essential subscription types give each Business Central customer one production environment and
three sandbox environment free of extra charge. If the customer requires more production environments, they can buy
additional environments through their CSP partner. Each additional production environment comes with three additional
sandbox environments and 4 GB additional, tenant-wide database capacity. In addition, starting in 2023 release wave 2,
there's a limit on how many companies you can have on a single tenant (see Operational limits).

Administrators can create the additional environments in the Business Central administration center. The
environments can be created and used in any country or region where Business Central is available, including
the countries or regions where the customer's existing environments are running. The environments quota is
applied when you try to create a new environment, or copy an existing environment, in the Business Central
administration center.
Each environment can be divided into multiple companies, where each company defines a legal entity or a
business unit that has separate accounting requirements. All users who have a Business Central license for a
specific Azure AD tenant can access all companies in each Business Central environment that the Azure AD
tenant has. You can define different permissions inside Business Central. For more information, see Create Users
According to Licenses in the business functionality content.

Example
Let's review a scenario for an organization that is based in Denmark but has a subsidiary in Germany. They have
three business units in Denmark and two in Germany. The following diagram illustrates how this fictitious
company has set up their Business Central:

In this example, the production environment that is based on the Danish localization of Business Central is part
of the default assignment as described earlier. This production environment has three companies to represent
the following business units, all located in central Jutland:
The administrative headquarters
The production facilities
The Danish sales office
Contoso has chosen to add a sandbox environment with two companies so that their users can train new
employees in a safe environment. The sandbox started out as a copy of the Danish production environment.
Over time, it has become a proper training ground with some sample data that Contoso's reselling partner came
up with for them.
Because Contoso has a German subsidiary that has separate accounting requirements, they decided to buy
another production environment. This extra environment has two companies, one for the sales offices in
Munich, and one for the warehouse near Stuttgart.
The users in all three environments are defined in the same Azure AD tenant. This way, all licensed users can
work in all environments. Individual access to various capabilities is controlled through permissions.
Alternatively, the organization could have chosen to use a separate Azure AD tenant for the German subsidiary
so that the German environment could use the Essentials license type rather than the Premium license type.
The following diagram illustrates how things would look for Contoso if they wanted to use two different license
types:

In this type of configuration, users from the Danish Azure AD tenant cannot access the German environments.
However, Business Central supports consolidation of financial data from different companies so that Contoso's
HQ can still get a complete overview of the business.

IMPORTANT
As the examples illustrate, the Azure AD tenant plays an important role in how users can access Business Central. Users
from one Azure AD tenant cannot access environments that belong to another Azure AD tenant.

Contoso is just an example to illustrate how the Azure AD tenant both affects and reflects the organizational
structure. In some cases, this example is overly simplistic; in other cases, the example is too complicated. We
recommend that customers work closely with their Microsoft reselling partner to understand how to configure
their Business Central online.

TIP
For information about how to find out which Azure region a Business Central environment is deployed to, see the
overview at Country/regional availability and supported languages.

See Also
Administration of Business Central Online
Production and Sandbox Environments
The Business Central Administration Center
The Business Central Administration Center API
Version numbers in Business Central
Monitoring and Analyzing General Data Protection Regulation
Get Started as a Reseller of Business Central Online
Deliver consulting services as a VAR: aka.ms/BusinessCentralConsultingServices
Get Started as a Reseller of Business Central Online
2/6/2023 • 12 minutes to read • Edit Online

If you want to build your business on Dynamics 365 Business Central online, you must get set up as a reseller in
the Microsoft Partner Center. In this article, we take you through the first steps in your journey.

Step 1: Become a partner


Becoming a Microsoft partner gives you access to the Microsoft resources needed to sell solutions. The steps in
this section below are required to gain access to the programs that enable are intended to help you get set up to
sell Business Central.
In order to be able to service Business Central licenses and provide help and support to your customers, your
company must have a Microsoft Partner ID (MPN ID), and you must enroll in the Cloud Solution Provider (CSP)
program.
Join the Microsoft Partner Network
Microsoft Partner Network (MPN) membership unlocks our best resources to differentiate your business, take
your product to market, and sell your solutions. To become a partner, you must join the Microsoft Partner
Network (MPN), at which time you will be assigned an MPN ID. MPN membership is free to all partners; you can
enroll in the MPN here.
Once signed up, you will get an MPN ID – your gateway to access all the membership resources and benefits for
your partnership with Microsoft. There is no cost to obtain a MPN ID as a Network member, and with options to
upgrade to an Action Pack subscription or work toward a competency, you can access even more benefits.
Set up your Partner Center account
Once you have joined the Microsoft Partner Network (MPN), you can set up your Partner Center (PC) account.
The Microsoft Partner Center is a generic portal where partners can sell and manage customer subscriptions for
Microsoft services, such as Microsoft 365, Azure, Dynamics 365, and others, as well as for some third-party
products. For more information, see the Partner Center documentation.
Your Partner Center account provides you with access to pricing information, tools and services, and enables
you to manage admin credentials for your company's work account. Partner Center is also where you can
purchase or renew subscriptions to Microsoft Action Packs, create a business profile to receive and manage
sales leads from Microsoft, and see if you qualify for co-selling opportunities.
Enroll in the CSP program
The Cloud Solution Provider (CSP) program helps your company to be more involved in your customers'
businesses, beyond reselling licenses. In CSP, you can choose to enroll as an indirect reseller or a direct bill
partner.
In most cases, you will enroll as an indirect reseller and then work with an indirect provider, also referred to as a
distributor, who then manages all interaction with Microsoft in terms of licensing and technology, so that you
can focus on sales and support. If you decide to enroll as a direct bill partner in order to fully own the end-to-
end relationship with both customers and Microsoft, make sure that you meet the eligibility requirements. For
more information, see Enroll in the Cloud Solution Provider program in the Microsoft Partner Center content.
The Microsoft Partner Center is a generic portal where partners can sell and manage customer subscriptions for
Microsoft services, such as Microsoft 365, Azure, Dynamics 365, and others, as well as for some third-party
products. For more information, see the Partner Center documentation.
Some indirect providers (distributors) provide their resellers with a custom portal that optimizes and enhances
the experience beyond the Partner Center. They can also provide indirect resellers with an API to automate some
of the customer onboarding steps. Contact your indirect provider to find out more.
Both indirect resellers and direct bill partners can access and support their customers' Business Central by
setting up a reseller relationship with them.
To service customers in a specific country, your partner company's Azure Active Directory (Azure AD) tenant and
CSP account must be registered in the regional CSP market that covers that country. For more information, see
Cloud Solution Provider program regional markets and currencies.

NOTE
When you buy Business Central offers on behalf of your CSP customers, the CSP offer must be available in both your own
tenant's country and in your customer's tenant's country. For example, if your tenant is located in Slovakia and the
customer's tenant is in Germany, you will not be able to sell Dynamics 365 Business Central Premium to that customer,
because this offer is currently not available in Slovakia.
Similarly, if your tenant is located in Germany and the customer's tenant is in Slovakia, you will not be able to sell
Dynamics 365 Business Central Premium to that customer, because this offer is currently not available in Slovakia.

In the Microsoft Partner Center documentation, you can learn how to request a reseller relationship with
customers, assign licenses to users, and create new subscriptions. Business Central is one of the subscriptions
that you can create, and there are Business Central-specific license types that you can assign to users.
You must also assign certain roles to users in your own organization so that they can support your customers.
Add users from your own organization
In most cases, your partner company includes employees with different responsibilities, and you can assign
different roles depending on people's responsibility. This way, you can be very explicit about who from your staff
can access your customers' data, for example.
For each user, you can assign permissions for 2 categories of tasks:
Managing your organization's account
This controls access to the functionality of the Partner Center portal
Assisting your customers
This controls access to your customers' environments
When you establish a reseller relationship with a customer in Partner Center, you must specify which people
from your organization will assist that customer's tenant as either Admin agent or Helpdesk agent. These users
can manage implementation, support, and troubleshooting tasks for your customers. Once the reseller
relationship with a customer is established, they will be able to login into the Business Central environments of
the customer without a license. The number of partner users that can access customer environments is not
restricted.
This way of accessing customer resources is called delegated administration, and the partner users are therefore
called delegated administrators or delegated admins in daily shorthand. For more information, see Delegated
Administrator Access to Business Central Online.
Since February 2022, you can set up security groups with granular delegated admin privileges to better control
who has access to which customers with which level of access to the customer's Business Central environment.
This way, the delegated admins no longer have to be global admins for the customer's Active Directory. For
more information, see the Delegated Administrator Access to Business Central Online section, and also the
Admin roles article in the Microsoft 365 admin content.
NOTE
These users cannot provide accounting services for the customers. For this purpose, the customers must use the
External Accountant license, which is also available via CSP.

Cau t i on

Quite often, partner users are registered as business-to-business (B2B) guest users in their customer's Azure
Active Directory (Azure AD), such as to collaborate through Teams. However, when a partner user is added as a
guest to their customer's Azure AD, they can no longer log in as a delegated admin into the customer's Business
Central. These guest users do not have a valid Business Central license assigned to them. But if the partner user
has granular delegated admin privileges, they can access the customer's Business Central administration center
and manage the environments there. Starting in 2022 release wave 2, partner users that are guest users and
have granular delegated admin privileges are no longer blocked from accessing Business Central. But we
continue to consider it a best practice that customers do not invite partner users to their tenant as guests but
ask them to set up granular delegated admin privileges, using the Dynamics 365 administrator role. For more
information, see Move to GDAP and remove DAP in the Partner Center FAQ.
For more information, see Delegated Administrator Access to Business Central Online.

Step 2: Go to market
When you become a Microsoft Partner Network member, you gain access to membership benefits that can help
you build and grow your business. For more information, see Explore your Go-To-Market with Microsoft offers
in the Partner Center docs.
As a Dynamics 365 reseller, you benefit from Microsoft's investments in an always up-to-date modern platform,
you can bundle recognized apps from the Microsoft commercial marketplace into an offering that fits the needs
of your customers, reach more customers by using Microsoft's commercial marketplace to promote your
packaged consulting service offerings or customization services, and streamline your own processes and build
tools with Power BI, Power Automate, and Power Apps connected to Business Central.
The Dynamics 365 Business Central Partner Portal landing site has plenty of material to help you build a
practice, go to market, drive readiness, and keep track of upcoming events (requires a partner account).
Marketing assets
Microsoft provides marketing assets that you can use to build a business based on Microsoft. For more
information, see the following sites:
Partner Network resources
Brand and trademark basics for partners
Go-to-market with Microsoft
Specifically for going to market with Business Central, Microsoft provides resources and guidance on the
Business Applications for small and medium-sized businesses (SMBs) site. For more information, see Business
Central Go-To-Market resources.

Step 3: Give powerful demos


You can create a trial environment based on content in cdx.transform.microsoft.com.
For more information, see Preparing Demonstration Environments of Dynamics 365 Business Central.

Step 4: Help your customers get started


When you onboard customers to Business Central, you have access to their account as a delegated
administrator and can help them get things set up. For more information, see Administration of Business Central
Online.
Connect with customers
As a CSP partner, you can manage a customer's subscriptions and services on their behalf in the Partner Center
by establishing a reseller relationship with your customers. If they already have an account, such as if they
currently use Microsoft 365, other Dynamics 365 apps, or PowerApps, for example, you can send them an
invitation straight from the Partner Center. For more information, see Connect with customers in Partner Center
(indirect providers/distributors) and Connect with customers (indirect resellers).
When the customer's internal administrator receives the invitation link and navigates to it, they must
acknowledge that they have read the Microsoft Customer Agreement and that they can authorize you as their
reseller on behalf of their organization. For more information, see Confirm customer acceptance of the
Microsoft Customer Agreement.
When a customer accept this reseller relationship, delegated administration privileges must be set up . For more
information, see Delegated Administrator Access to Business Central Online.
If you are working as an indirect reseller, your indirect provider (distributor) must associate your customers with
you in their Partner Center.
The customer can decide to remove their partner's delegated admin privileges from their tenant, but still retain
the relationship with their partner for subscription and license renewal purposes. Removing delegated admin
privileges will block the partner's access to the customer's Business Central. The access can be restored if the
partner sends the reseller relationship request to the customer again.
If the customer wants to cancel their relationship with their partner, the partner must remove the relationship in
Partner Center.
Get Business Central right for the customer
The default version of Business Central is just that - a default version. In many cases, you'll enhance the default
version with apps from the Microsoft commercial marketplace. But you can also customize pages for a profile
and change which UI elements are visible. For more information, see Customize Business Central in the business
functionality content.
If your customer wants more tweaks, you can create customizations of profiles and pages in code. For more
information, see Customizing the User Interface for User Roles in the developer content.
You can also use configuration packages to quickly apply the same settings as usual to new environments.
Move the customer from a trial to a paid subscription
If your customer decides to start using Business Central to run their business, they must switch to a paid
subscription. Both the internal admin and the delegated admin can assign licenses to users in the Microsoft 365
admin center. For more information, see Buy or remove licenses in the Microsoft 365 content.

IMPORTANT
Specifically for businesses who want to convert a 30-day trial company into their actual production company, the first
user who signs into Business Central after the license was applied to their tenant must be a user with this license
assigned. This way, the 30-day trial ends, and any trial-related notifications disappear so that users can use Business
Central to do work.
If an administrator is the first person to sign in after the license was applied to the tenant and to users, then the trial will
continue until it expires.

If the customer has tried out Business Central using a pre-configured demonstration company that you have
prepared in other ways, they can now sign up for Business Central using their own work or school account so
that you can assign the Business Central license to their Microsoft 365 tenant.
You can help them migrate their data from their legacy system. For more information, see Migrate On-Premises
Data to Business Central Online.

Step 5: Configure the support experience


As a Business Central reselling partner, you are an administrator of your customers' Business Central tenants,
and you are the first line of support. This means that you will get requests for support from your customers that
you must triage, investigate, and either resolve or escalate to Microsoft.
Your company must be registered as a Microsoft partner, and it must have the Advanced Support for Partners
(ASfP) or Premier support plan. Your service account manager can get you more information about getting the
ASfP. If you already have a support plan, the Technical Benefits tab in the Partner Center lists the contract ID and
access ID that you must specify when you submit a new support request on behalf of your customer. If you're
not sure how to find the information, the service account manager can get the information for you.
For more information, see Technical Support for Business Central and Managing Technical Support.

Step 6: Maintain your customers' Business Central


As a Business Central reselling partner, you are the administrator of the Business Central tenants of your
customers. You are expected to help your customers maintain their solution, including setting the upgrade
window, monitoring telemetry, updating customizations, and managing apps.
For more information, see Administration of Business Central Online and The Business Central Administration
Center.

See also
Administration of Business Central Online
Deployment of Dynamics 365 Business Central on-premises
Trials and Sign-ups for Business Central Online
Licensing in Dynamics 365 Business Central
Learn how to partner with indirect providers in the Cloud Solution Provider program
Dynamics 365 Business Central Partner Portal
Country/regional availability and supported
languages
2/6/2023 • 7 minutes to read • Edit Online

This page lists the countries/regions where Dynamics 365 Business Central is available and which languages are
supported.

NOTE
In countries where Microsoft has not delivered a localization, partners can build localizations using translation and
localization apps that are published on AppSource. These apps are built on top of the international (W1) version of
Dynamics 365 Business Central.

The following table provides the list of all countries/regions where Dynamics 365 Business Central is available
or in planning for future availability. The table also specifies the abbreviation of the relevant country-specific
environment that you'll see in the admin center. Finally, the table and states whether the localization is provided
by Microsoft or partner(s).

NOTE
Availability in the list concerns Dynamics 365 Business Central online. It does not apply to partner localizations. Please
check partner localization app availability on AppSource.

Countries and regions


EN VIRO N M EN T
C O UN T RY
C O UN T RY / REGIO N LO C A L IZ ED B Y AVA IL A B IL IT Y A B B REVIAT IO N A Z URE REGIO N

Albania Partner Available AL West Europe,


Netherlands

Algeria Partner Available DZ South Africa North

Angola Partner Available AO South Africa North

Argentina Partner Available AR Brazil South

Australia Microsoft Available AU Australia East

Austria Microsoft Available AT West Europe,


Netherlands

Bahrain Partner Available BH UAE North

Bangladesh Partner Available BD Southeast Asia,


Singapore
EN VIRO N M EN T
C O UN T RY
C O UN T RY / REGIO N LO C A L IZ ED B Y AVA IL A B IL IT Y A B B REVIAT IO N A Z URE REGIO N

Belgium Microsoft Available BE West Europe,


Netherlands

Bosnia and Partner Available BA West Europe,


Herzegovina Netherlands

Botswana Partner Available BW South Africa North

Bulgaria Partner Available BG West Europe,


Netherlands

Brazil Partner Available BR Brazil South

Canada Microsoft Available CA Canada Central

Chile Partner Available CL Brazil South

Colombia Partner Available CO Brazil South

Costa Rica Partner Available CR Brazil South

Croatia Partner Available HR West Europe,


Netherlands

Cyprus Partner Available CY West Europe,


Netherlands

Czechia Microsoft Available CZ West Europe,


Netherlands

Denmark Microsoft Available DK North Europe,


Ireland

Dominican Republic Partner Available DO Brazil South

Ecuador Partner Available EC Brazil South

El Salvador Partner Available SV Brazil South

Egypt Partner Available EG South Africa North

Estonia Partner Available EE North Europe,


Ireland

Faroe Islands Microsoft Available DK North Europe,


(Denmark) Ireland

Finland Microsoft Available FI North Europe,


Ireland

France Microsoft Available FR France Central


EN VIRO N M EN T
C O UN T RY
C O UN T RY / REGIO N LO C A L IZ ED B Y AVA IL A B IL IT Y A B B REVIAT IO N A Z URE REGIO N

Georgia Partner Available GE West Europe,


Netherlands

Germany Microsoft Available DE Germany West


Central

Greece Partner Available GR West Europe,


Netherlands

Greenland (Denmark) Microsoft Available DK West Europe,


Netherlands

Guatemala Partner Available GT Brazil South

Honduras Partner Available HN Brazil South

Hong Kong SAR Partner Available HK Southeast Asia,


Singapore

Hungary Partner Available HU West Europe,


Netherlands

Iceland Microsoft Available IS North Europe,


Ireland

India Microsoft Available IN Central India

Indonesia Partner Available ID Southeast Asia,


Singapore

Ireland Partner Available IE North Europe,


Ireland

Israel (no RTL; English Partner Available IL UAE North


only)

Italy Microsoft Available IT West Europe,


Netherlands

Jamaica Partner Available JM South Central US

Japan Partner Available JP Japan East, Japan

Jordan Partner Available JO UAE North

Kenya Partner Available KE South Africa North

Kuwait Partner Available KW UAE North

Latvia Partner Available LV North Europe,


Ireland
EN VIRO N M EN T
C O UN T RY
C O UN T RY / REGIO N LO C A L IZ ED B Y AVA IL A B IL IT Y A B B REVIAT IO N A Z URE REGIO N

Lebanon Partner Available LB UAE North

Lithuania Partner Available LT North Europe,


Ireland

Luxembourg Partner Available LU West Europe,


Netherlands

Malaysia Partner Available MY Southeast Asia,


Singapore

Maldives Partner Available MV Southeast Asia,


Singapore

Malta Partner Available MT West Europe,


Netherlands

Mauritius Partner Available MU South Africa North

Mexico Microsoft Available MX South Central US

Monaco (France) Partner Available MC France Central

Mongolia Partner Available MN Southeast Asia

Montenegro Partner Available ME West Europe,


Netherlands

Morocco Partner Available MA South Africa North

Netherlands Microsoft Available NL West Europe,


Netherlands

New Zealand Microsoft Available NZ Australia East

Nicaragua Partner Available NI Brazil South

Nigeria Partner Available NG South Africa North

North Macedonia Partner Available MK West Europe,


Netherlands

Norway Microsoft Available NO Norway East

Oman Partner Available OM UAE North

Pakistan Partner Available PK Central India

Panama Partner Available PA Brazil South


EN VIRO N M EN T
C O UN T RY
C O UN T RY / REGIO N LO C A L IZ ED B Y AVA IL A B IL IT Y A B B REVIAT IO N A Z URE REGIO N

Paraguay Partner Available PY Brazil South

Peru Partner Available PE Brazil South

Philippines Partner Available PH Southeast Asia,


Singapore

Poland Partner Available PL West Europe,


Netherlands

Portugal Partner Available PT West Europe,


Netherlands

Puerto Rico Partner Available PR Brazil South

Qatar Partner Available QA UAE North

Romania Partner Available RO West Europe,


Netherlands

Russia (on- Microsoft Available (Not listed) N/A


premises only)

Saudi Arabia Partner Available SA UAE North

Serbia Partner Available RS West Europe,


Netherlands

Singapore Partner Available SG Southeast Asia,


Singapore

Slovakia Partner Available SK West Europe,


Netherlands

Slovenia Partner Available SI West Europe,


Netherlands

South Africa Partner Available ZA South Africa North

South Korea Partner Available KR Korea Central, Korea

Spain Microsoft Available ES West Europe,


Netherlands

Sri Lanka Partner Available LK Southeast Asia,


Singapore

Sweden Microsoft Available SE North Europe,


Ireland

Switzerland Microsoft Available CH Switzerland North


EN VIRO N M EN T
C O UN T RY
C O UN T RY / REGIO N LO C A L IZ ED B Y AVA IL A B IL IT Y A B B REVIAT IO N A Z URE REGIO N

Taiwan Partner Available TW Southeast Asia,


Singapore

Thailand Partner Available TH Southeast Asia,


Singapore

Trinidad and Tobago Partner Available TT Brazil South

Tunisia Partner Available TN South Africa North

Türkiye Partner Available TR West Europe,


Netherlands

Ukraine Partner Available UA West Europe,


Netherlands

United Arab Emirates Partner Available AE UAE North

United Kingdom Microsoft Available GB UK West

United States Microsoft Available US East US

Uruguay Partner Available UY Brazil South

Vietnam Partner Available VN Southeast Asia,


Singapore

Zimbabwe Partner Available ZW South Africa North

For an overview of where Business Central online is deployed, see the Geographical availability site.

Important information regarding planned availability


Due to the nature of the joint effort where Microsoft is providing the international (W1) cloud service and
partners are providing localization app(s), the above planned availability estimates represent the earliest
possible availability and can be exceeded if localization partners have not successfully published their app(s) to
AppSource by this time.

Supported languages
To maximize productivity Dynamics 365 Business Central supports many languages. It is important to know that
language support requires translation of platform captions and application captions (UI). Translated platform
captions are provided by Microsoft for all supported languages. Application languages are provided by both
Microsoft and partners, depending on the language.
Application languages delivered by Microsoft are provided as language apps, available on AppSource, that can
be installed if needed. Partners can also provide application translation for any platform supported language. To
use one of these languages the app publisher must be contacted through AppSource.
This table gives an overview of supported languages and how application languages are provided.
L A N GUA GE LO C A L E T RA N SL AT IO N A P P P RO VIDED B Y

Bulgarian bg-BG Partner, Available on AppSource


(pending)

Czech (Czech Republic) cs-CZ Microsoft, Available on AppSource

Danish (Denmark) da-DK Microsoft, Available on AppSource

German (Austria) de-AT Microsoft, Available on AppSource

German (Switzerland) de-CH Microsoft, Available on AppSource

German (Germany) de-DE Microsoft, Available on AppSource

English (Australian) en-AU Microsoft, Available on AppSource

English (Canada) en-CA Microsoft, Available on AppSource

English (Great Britain) en-GB Microsoft, Available on AppSource

English (New Zealand) en-NZ Microsoft, Available on AppSource

English (United States) en-US Built-in

English (South Africa) en-ZA Supported by platform, no app


available

Spanish (Spain) es-ES Microsoft, Available on AppSource

Spanish (Mexico) es-MX Microsoft, Available on AppSource

Estonian (Estonia) et-EE Partner, Available on AppSource

Finnish (Finland) fi-FI Microsoft, Available on AppSource

French (Belgium) fr-BE Microsoft, Available on AppSource

French (Canada) fr-CA Microsoft, Available on AppSource

French (Switzerland) fr-CH Microsoft, Available on AppSource

French (France) fr-FR Microsoft, Available on AppSource

Greek (Greece) el-GR Partner, Available on AppSource

Croatian (Croatia) hr-HR Partner, Available on AppSource

Hungarian (Hungary) hu-HU Partner, Available on AppSource

Icelandic (Iceland) is-IS Microsoft, Available on AppSource


L A N GUA GE LO C A L E T RA N SL AT IO N A P P P RO VIDED B Y

Italian (Switzerland) it-CH Microsoft, Available on AppSource

Italian (Italy) it-IT Microsoft, Available on AppSource

Japanese (Japan) ja-JP Partner, Available on AppSource

Korean (Korea) ko-KR Partner, Available on AppSource

Latvian (Latvia) lv-LV Partner, Available on AppSource

Lithuanian (Lithuania) lt-LT Partner, Available on AppSource

Norwegian, Bokmål (Norway) nb-NO Microsoft, Available on AppSource

Dutch (Belgium) nl-BE Microsoft, Available on AppSource

Dutch (Netherlands) nl-NL Microsoft, Available on AppSource

Polish (Poland) pl-PL Partner, Available on AppSource

Portuguese (Brazil) pt-BR Partner, Available on AppSource

Portuguese (Portugal) pt-PT Partner, Available on AppSource

Romanian ro-RO Partner, Available on AppSource


(pending)

Russian (Russia) ru-RU Microsoft, Available on AppSource

Slovak (Slovakian) sk-SK Partner, Available on AppSource


(pending)

Slovenian (Slovenia) sl-SI Partner, Available on AppSource

Serbian (Serbia) sr-latn-RS Partner, Available on AppSource

Swedish (Sweden) sv-SE Microsoft, Available on on AppSource

Turkish (Türkiye) tr-TR Partner, Available on AppSource

Traditional Chinese (Hong Kong SAR) zh-HK Partner, Available on AppSource

Traditional Chinese (Taiwan) zh-TW Partner, Available on AppSource

Ukrainian (Ukraine) uk-UA Partner, Available on AppSource

Vietnamese (Vietnam) vi-VN Partner, Available on AppSource


NOTE
Application translations provided by Microsoft cover features in the international version (W1). Local functionality is not
translated to all languages and will be provided in English and native language, as has been done historically. As a result,
you may experience a mix of translations if using Dynamics 365 Business Central in a foreign language.

See Also
Rules and Guidelines for AL Code
Checklist for Submitting Your App
Delegated Administrator Access to Business Central
Online
2/6/2023 • 10 minutes to read • Edit Online

As a Business Central reselling partner, you must set up your employees to work in Partner Center, and you
must assign employees to support your customers. When you request a reseller relationship with a customer,
you can choose to include delegated administration privileges for Azure Active Directory (Azure AD) and
Microsoft 365 in the request email that you send to the customer.

TIP
Since February 2022, you can request access to your customer's tenant with granular delegated admin privileges. This
way, you set up security groups to specify which users in your own organization must have access to a specific customer
as Dynamics 365 administrator or any other role you prefer. For more information, see Introduction to granular delegated
admin privileges (GDAP) in the Partner Center content. We recommend that you switch off any existing relationship and
request granular delegated admin privileges instead. For more information, see the GDAP FAQ.

When a customer accepts a partner's request for granular delegated administration privileges, the relevant
members of the specified security group in the partner's Azure AD tenant get access as indicated in the
following list:
The Dynamics 365 Administrator role gives access to manage Dynamics 365 for the customer, including
support requests
The Service Support Administrator role gives access to manage support requests on the customer's behalf
The Helpdesk Administrator role gives access to the customer's Azure AD tenant.
For more information, see Least-privileged roles in the GDAP section of the Partner Center content.
The members of the security group have either the Admin agent or Helpdesk agent role in your own Azure AD
tenant. For more information, see Assign roles and permissions to users.
For certain tasks, you can access the Business Central administration center, which is a powerful tool for you to
manage your customers' tenants. From the administration center, you can manage upgrades and access the
tenants as the delegated administrator. For more information, see The Business Central Administration Center.

TIP
Always include the domain or the Azure Active Directory ID of the customer in the URL when you log in as a delegated
admin, such as in https://businesscentral.dynamics.com/contoso.com/admin . This way, you always know exactly
which customer you are trying to access.

Cau t i on

Quite often, partner users are registered as business-to-business (B2B) guest users in their customer's Azure
Active Directory (Azure AD), such as to collaborate through Teams. However, when a partner user is added as a
guest to their customer's Azure AD, they can no longer log in as a delegated admin into the customer's Business
Central. These guest users do not have a valid Business Central license assigned to them. But if the partner user
has granular delegated admin privileges, they can access the customer's Business Central administration center
and manage the environments there. Starting in 2022 release wave 2, partner users that are guest users and
have granular delegated admin privileges are no longer blocked from accessing Business Central. But we
continue to consider it a best practice that customers do not invite partner users to their tenant as guests but
ask them to set up granular delegated admin privileges, using the Dynamics 365 administrator role. For more
information, see Move to GDAP and remove DAP in the Partner Center FAQ.

Managing delegated permissions as a partner


Delegated administrators aren't visible in the customer's Azure AD user list and can't be managed by the
customer's internal admin. However, when a delegated admin logs into a Business Central environment on
behalf of their customer, they're automatically created as a user inside Business Central. This way, the actions
performed by a delegated admin are logged in Business Central, such as posting documents, and associated
with their user ID.
With granular delegated admin privileges (GDAP), the user is shown in the Users list and can be assigned any
permissions. They aren't shown with name and other personal information but with a unique ID and their
company name. Both internal and external admins can see these users in the Users list, and they have full
transparency into what these users do through the change log, for example. But they can't see the actual name
of these users. GDAP users are listed with user names such as USER_1A2B3C4D5E6F , and an email address such as
USER_1A2B3C4D5E6F@partnerA.com , which isn't the person's actual email address. Because they aren't part of their
customer's Azure AD, their authentication email address isn't an email address at all but reflects the company
that they work for, such as Partner A . This way, the GDAP user accounts don't reveal personal information. If
you need to find out who the person behind such a pseudonym is, you'll have to reach out to the company that
this user works or worked for.
At the partner company, we encourage you to keep track of which user names your technicians and consultants
have in your customers' Business Central tenants. For example, you have a consultant who is an admin with
GDAP in your partner company's five customers' Business Central. Your consultant can see which customers
they have GDAP access to in the Granular administration list in the Administer page in Partner Center. But
as an organization, you can also maintain a list of names and IDs.
If a customer removes delegated permissions from you, you can still manage their subscription from the Partner
Center, such as adding or removing licenses for their subscription, but you'll no longer be able to log into and
manage their Business Central environment, Azure AD, and other services. You'll also not be able to manage
their users (add/remove/assign licenses) from the Customer page in the Partner Center.
Restricted access to Business Central as delegated administrator
When you sign in to your customers' Business Central as the delegated administrator from the Business Central
administration center, you have access to all areas of their Business Central. However, because you aren't
registered as a regular user, there are certain tasks that you can't do.
The following tasks aren't available to the delegated administrator:
Run scheduled tasks in the job queue.
However, delegated administrators can test that the job queue can run without issues, before asking their
customer to start it, by using the Run once (foreground) action on the Job Queue Entr y card. This
action creates a temporary non-recurrent copy of this job and runs it once in the foreground. You can
then call it as many times as you need before you hand it over to your customer so that they can start it
as a recurrent job. After the job queue completes, it will be put in the on-hold status and can't be
rescheduled.
Trigger a web hook or any other application action that relies on the job queue functionality, except by
using the Run once (foreground) action.
Use the Invite External Accountant assisted setup guide
Instead, you can add the external user in the Azure portal and assign this user the External Accountant
license.
Access a web service by using a Web Service Access key.
Usage of Web Service Access key was deprecated in 2022 release wave 1. Find out more here.

NOTE
Customers can choose to configure conditional access that may restrict delegated admin access further. For example, it's a
best practice to set up a conditional access policy to require multi-factor authentication for admins, and to set up terms of
use policies. Learn more at Azure AD Conditional Access documentation.

Managing delegated permissions as an internal administrator


As a Microsoft customer organization, you can have multiple partners registered as your resellers. It isn't
unusual for a single organization to use one partner as the delegated admin for their Microsoft 365 subscription
and another for Business Central, for example. However, as soon as the delegated administration right is granted
in the Microsoft 365 admin center, you can't restrict partner access to a specific service only. The delegated
admin access applies to all Microsoft services that your organization subscribes to.

TIP
If the partner has requested access to your tenant using granular delegated admin privileges, then you can see the
relevant users in the Users list in Business Central, and you can see them in the Sign in log in your Microsoft 365 admin
center. With granular delegated admin privileges, the partner typically does not have global admin access to your tenant
but only access to Dynamics 365. You will not be able to see the name of the partner user, but you can see an ID and the
name of their company.

Delegated administrators aren't visible in the customer's Azure AD user list and can't be managed by the
customer's internal admin. However, when a delegated admin logs into a Business Central environment on
behalf of their customer, they're automatically created as a user inside Business Central. This way, the actions
performed by a delegated admin are logged in Business Central, such as posting documents, and associated
with their user ID.
With granular delegated admin privileges (GDAP), the user is shown in the Users list and can be assigned any
permissions. They aren't shown with name and other personal information but with a unique ID and their
company name. Both internal and external admins can see these users in the Users list, and they have full
transparency into what these users do through the change log, for example. But they can't see the actual name
of these users. GDAP users are listed with user names such as USER_1A2B3C4D5E6F , and an email address such as
USER_1A2B3C4D5E6F@partnerA.com , which isn't the person's actual email address. Because they aren't part of their
customer's Azure AD, their authentication email address isn't an email address at all but reflects the company
that they work for, such as Partner A . This way, the GDAP user accounts don't reveal personal information. If
you need to find out who the person behind such a pseudonym is, you'll have to reach out to the company that
this user works or worked for.
Customers can choose to configure conditional access that may restrict delegated admin access further. For
example, it's a best practice to set up a conditional access policy to require multi-factor authentication for
admins, and to set up terms of use policies. Learn more at Azure AD Conditional Access documentation.
If you don't need delegated admin help continuously, you can restrict access for the partner users into your
environment. There are two approaches that you can use to restrict delegated admin access to a Business Center
environment:
Disable a specific delegated admin user within the Business Central environment. For more information, see
How to remove a user's access.
Revoke delegated administration rights from all partner users at once in the Microsoft 365 admin center,
without breaking the reseller relationship with the partner.
In the Microsoft 365 admin center, internal administrators can find information about their partner relationships
in the Settings/Partner Relationship menu. On the same page, you can remove delegated permissions from the
partner, to restrict their access to Business Central and other services, while still keeping the reseller relationship
with them.
If you then want to allow access to your environment again, you can ask the partner to share the "Request a
reseller relationship" invitation link with you again.
For more information, see Customers delegate administration privileges to partners in the Partner Center
content.

NOTE
Quite often, partner users are registered as business-to-business (B2B) guest users in their customer's Azure Active
Directory (Azure AD), such as to collaborate through Teams. However, when a partner user is added as a guest to their
customer's Azure AD, they can no longer log in as a delegated admin into the customer's Business Central. These guest
users do not have a valid Business Central license assigned to them. But if the partner user has granular delegated admin
privileges, they can access the customer's Business Central administration center and manage the environments there.
Starting in 2022 release wave 2, partner users that are guest users and have granular delegated admin privileges are no
longer blocked from accessing Business Central. But we continue to consider it a best practice that customers do not
invite partner users to their tenant as guests but ask them to set up granular delegated admin privileges, using the
Dynamics 365 administrator role. For more information, see Move to GDAP and remove DAP in the Partner Center FAQ.

See also
Administration of Business Central Online
Get Started as a Reseller of Business Central Online
Exporting Databases
Business Central Trials and Subscriptions
2/6/2023 • 9 minutes to read • Edit Online

Organizations across the world sign up for a free Business Central trial to explore the experience. Then, when
they're ready, they talk to a reselling partner about getting a subscription. In this article, we describe how the
different types of trials work, and how the admin can remove licenses from users or cancel a subscription.

Get started with a trial


Any organization in the supported markets can sign up for a free trial from the
https://dynamics.microsoft.com/business-central/ page. To learn how to sign up, see the Sign up for a free
Dynamics 365 Business Central trial article.

NOTE
To explore the full capabilities in Business Central, change the user experience to Premium in the Company Information
page. For more information, see Change Which Features are Displayed in the business functionality content.

Depending on the country or region, the trial includes the languages and functionality that the country or region
requires. For more information, see Changing Language and Locale.

NOTE
Business Central resellers can also set up tailored demo environments.

Dynamics 365 Business Central Premium Trial


In the Partner Center, you can find a special license type called the Dynamics 365 Business Central
Premium Trial license, which is a very different way to give a prospect or an existing customer a trial
experience using their own data. If you assigned the Dynamics 365 Business Central Premium Trial license
to a customer's account in the Partner Center, then that also expires after 30 days. You cannot extend the
Premium trial, but you can add one more Premium trial license to give the customer an extra 30 days of trial.
But when the second Premium trial expires, then the customer must either convert their trial to a paid
subscription, or they must sign up for the viral trial.
For more information, see Offer your customers trials of Microsoft products in the Partner Center
documentation. If you have technical difficulties assigning this license, contact Partner Center support. For more
information, see Report problems with Partner Center.
Cau t i on

Make sure you understand the limitations of this type of trial, before you offer it to a prospect or customer. It is
easy to convert this type of trial to a paid subscription, but if the prospect needs more than 30 days to decide, or
if they want to add more than 25 users, then the viral trial is probably a better fit for them.
Extend trials
An organization can sign up for a free trial of Business Central. When they first sign up for Business Central, they
get access to an evaluation version that does not include all capabilities in Business Central. They can then
switch to the 30 day trial experience to enable all capabilities.
However, sometimes a 30 day trial is not enough to decide if they want to buy Business Central. In that case,
they can extend their trial with an additional 30 days. For more information, see Need More Time to Decide
Whether to Subscribe? in the business functionality content for Business Central.

NOTE
If you are a reselling partner, we recommend that you set up demo environments for prospects that need longer time to
decide if they want to buy Business Central. You can also use demo environments to help customers train their
employees, for example. Using the 30 days trials for training should be limited to just that short period. However, demo
environments cannot be used for production. For more information, see Preparing Demonstration Environments.

If the prospect wants to extend the trial further than those 30 days, they must contact a partner. The partner can
extend it another 30 days if the delegated administrator signs into the prospect's Business Central and runs the
Extend Trial Period guide.
After those additional 30 days, the prospect must either purchase Business Central or abandon Business Central.
At this point, they will have had up to 90 days with the trial experience.

TIP
As a reselling partner, you can suggest your prospects sign up for a trial, but you can also help set up a customized
demonstration environment based on a sandbox environment or a trial environment. In both cases, you can easily add or
remove functionality based on your prospects' expectations. For more information, see Preparing Demonstration
Environments.

When a subscription expires, two special periods kick in:


Grace period
Data retention period
The grace period is a period of 30 days when the customer can still access the product without any restrictions.
After the grace period, the subscription enters the data retention period, which is another 90 days during which
only the admin users of the Azure Active Directory tenant can login into the product. After those 90 days,
Microsoft deletes the data automatically.
This policy is general across Microsoft's online offerings, as you can see in this example from Microsoft 365:
What happens to my data and access when my Microsoft 365 for business subscription ends?.
The same applies to trials that are based on the Dynamics 365 Business Central Premium Trial license. But
this does not apply to viral trials.

Add your own data to an empty trial company


To try out Business Central with production data, you can switch to a free 30-day trial without sample data. The
Set up my company assisted setup guide can help you specify basic information about your business.
Optionally, you can import data from your existing business management solution so that you can evaluate
Business Central with your own data. However, we strongly recommend that you don't use a free trial to help
run your business. Contact a reselling partner to learn more about how to get started with Business Central. The
partner can also help you migrate your data to Business Central online.
If 30 days aren't enough to decide, you can extend the trial. For more information, see the Extend trials section.
Set up a company in Business Central
The quick start articles can help with the first steps into setting up Business Central for an organization. Inside
Business Central, the Assisted Setup page lists the assisted setup guides that can help you. For more
information, see Get Ready for Doing Business.
Reset Business Central
If the data in a Business Central free trial, you can still start over with a fresh experience. Just create a new
evaluation company, and then delete the original company. Open the Companies page and choose the New
action to start the Create New Company assisted setup guide. The guide can help you set up a fresh
evaluation company with sample data. You can also create a copy of your current company, sign out, and then
sign into your new company.

IMPORTANT
When you share Business Central with other people from your organization, you must make sure other people are not
logged in when you delete a company.

When a free trial expires


Most trials are based on people signing up at https://dynamics.microsoft.com/business-central/. These viral
trials do not expire, unless the prospect switches to the 30-day trial, and provided that users access Business
Central frequently.

NOTE
If a Business Central viral trial is left unused for 45 days, Microsoft considers the trial as expired, and the Business Central
is deleted.
If the trial is converted to a paid subscription before the trial expires, the countdown to 45 days of non-usage does not
apply.

Get started with a subscription


Each time a user signs in during the trial period, a notification in a blue bar at the top displays the time
remaining. If an organization decides to subscribe, they must find a Business Central partner. For more
information, see How do I find a reselling partner? (business users) and Trials and Sign-ups for Business Central
Online (partners).

IMPORTANT
Specifically for businesses who want to convert a 30-day trial company into their actual production company, the first
user who signs into Business Central after the license was applied to their tenant must be a user with this license
assigned. This way, the 30-day trial ends, and any trial-related notifications disappear so that users can use Business
Central to do work.
If an administrator is the first person to sign in after the license was applied to the tenant and to users, then the trial will
continue until it expires.

For more information about what you can do with Business Central, see Get Ready for Doing Business and
Business Functionality.
Removing a subscription
If an organization decides to stop using Business Central, an administrator must remove the subscription in the
Microsoft 365 admin center. An email notification is sent to all administrators of the account. Deleting the
subscription blocks all users from accessing their Business Central, and deletes all data.

WARNING
The subscription is deleted immediately and can not be reactivated.
For more information, see Suspend or cancel a subscription in the Partner Center content.

Data and access when a trial or subscription ends


Trials can expire, and so can a paid subscription, such as if the organization does not renew the subscription,
stops payments, or if they cancel the subscription.
When a subscription expires, two special periods kick in:
Grace period
Data retention period
The grace period is a period of 30 days when the customer can still access the product without any restrictions.
After the grace period, the subscription enters the data retention period, which is another 90 days during which
only the admin users of the Azure Active Directory tenant can login into the product. After those 90 days,
Microsoft deletes the data automatically.
This policy is general across Microsoft's online offerings, as you can see in this example from Microsoft 365:
What happens to my data and access when my Microsoft 365 for business subscription ends?.
The same applies to trials that are based on the Dynamics 365 Business Central Premium Trial license. But
this does not apply to viral trials.

Get started with sandboxes


Sandbox environments are a way for you to practice with Business Central. Think of a sandbox as a non-
production environment that you use on top of your production instance of Business Central. For example, if
you want to take the free online training from Microsoft Learn, your administrator can create a sandbox
environment. This way, you and your colleagues can practice in a safe place rather than in your production
environment.
If you're a developer, a sandbox lets you safely build and test extensions and develop new functionality to
customize the service without affecting the data and settings of your production environment.
Right now, all customers can use a sandbox, including organizations who have signed up for a trial. For more
information about how to get started with a sandbox, see Sandbox Environments for Dynamics 365 Business
Central Development.

NOTE
Sandboxes created this way contain demonstration data for the fictitious CRONUS company. No data is copied or
otherwise transferred from the production environment.

The administrator of your Business Central and your reselling partner can create more environments in the
administration center. For more information, see The Business Central Administration Center.

Understanding Business Central online infrastructure


If you are migrating from an on-premises solution, understanding the infrastructure of Business Central online
can help you make good choices for how to set up environments and companies. For more information and an
example, see Understanding the infrastructure of Business Central online.

See also
Sign up for a free Dynamics 365 Business Central trial
Dynamics 365 Business Central trial FAQ
Trials and Sign-ups for Business Central Online
Migrate Data
Choosing Your Dynamics 365 Business Central Development Sandbox Environment
Country/Regional Availability and Supported Translations
Get Started as a Reseller of Business Central Online
Preparing Demonstration Environments (as a partner)
Major Updates and Minor Updates for Business
Central Online
2/6/2023 • 19 minutes to read • Edit Online

This article provides an overview of what you need to know about how a major or minor update for Business
Central rolls out, and how the underlying service updates. It includes key dates, actions you need take, and
answers some common questions.
Business Central online is a service that consists of a Microsoft-maintained platform and business functionality.
Many Microsoft partners provide extra business functionality, such as to address specific industry or localization
needs. Both business functionality and service components are monitored continuously and updated as
appropriate.
New capabilities roll out in release waves that consist of a major update and monthly minor updates. Most
capabilities are made available in major updates, but some become available in minor updates. Critical fixes roll
out as soon as possible after they pass tests and have been verified in Microsoft's protected staging
environment. You can always refer to the release plan for an overview of new and upcoming functionality. And
keep an eye out for the minor updates at aka.ms/bclastminorupdate.

TIP
All updates that Microsoft applies to Business Central online are also shipped with the subsequent cumulative update for
Business Central on-premises. For example, see Update 18.3 for Microsoft Dynamics 365 Business Central online 2021
release wave 1 and Dynamics 365 Business Central On-Premises 2021 Release Wave 1 Updates, respectively.

Microsoft is committed to delivering predictable updates to the service. Updates are continuous, touchless
updates that provide new features and functionality. They eliminate the need to do expensive upgrades every
few years. Administrators can set a maintenance window for each environment that determines when Microsoft
is allowed to update that environment. For more information, see Managing Updates in the Business Central
Admin Center. Microsoft then schedules updates of the business functionality to be applied during these
maintenance windows.
You are in control and manage how your organization receives these updates. Microsoft applies updates to each
environment based on your configuration. The only exception is how Microsoft maintains the underlying
platform with invisible updates during low traffic hours, for example. For more information, see the Service
updates section.
Each new update is designed and developed by the Dynamics 365 team. Any new update is first validated by the
feature team, then validated in combination with the full product. During this time, extensive testing is done on
various test topologies. A compatibility checker also runs tests to ensure backward compatibility.

Timelines for major updates


The following figure illustrates the key milestones and dates for rolling out a major update. The dates are loosely
based on 2021 release wave 1 and 2021 release wave 2. The same timeline applies to all other major updates,
though dates will differ.
TIP
Dates differ across countries and regions. Make sure that you have set up notifications in the Business Central
administration center so that you're notified when the next major update is available.

The following table describes the milestones with example dates for the two release waves in any given calendar
year.

M IL ESTO N E EXA M P L E DAT E WAVE 1 EXA M P L E DAT E WAVE 2 DESC RIP T IO N

Update is available April 1 October 1 The date when the new


major version of Business
Central becomes generally
available.

Update starts rolling out April 8 October 8 The default date when
Microsoft starts upgrading
your environments. Once
the update is scheduled,
you can change that date,
within the allowed date
range, to a date that suits
you better.

Last scheduled update date June 1 December 1 The last date you can
choose to extend your
upgrade date to.

IMPORTANT
The update window was temporarily extended during the CoViD-19 pandemic and throughout 2022 release wave 2 and
2023 release wave 1. In 2022 release wave 2 and 2023 release wave 1, the update window remains 60 days. Based on
feedback, we're currently evaluating the best longer-term processes for major updates and update windows. We expect
that on October 1, 2023, when we release 2023 release wave 2, new policies will be in place that could include a return to
an update window that again is 30 days after an update is available.
We recommend that you keep any apps and per-tenant extensions ready for upgrade at any given time, and that you
actively test compatibility. We encourage everyone to use the time until October 1, 2023, to get apps, per-tenant
extensions, and processes ready for a shorter update window.
TIP
There are many benefits to keeping code current and staying on top of updates. Microsoft and members of the
community continue to provide more and more tools and best practices to help.
Developers can get tips and guidance in the developer docs here: Maintain AppSource Apps and Per-Tenant Extensions.
Admins can install, update, and uninstall apps in the Business Central administration center as described here: Managing
Apps.

Timelines for minor updates


The monthly minor updates contain both application and platform changes that are critical improvements to the
service, including regulatory updates.
A minor update will roll out across Azure regions over several days and weeks. When the update is available for
a specific environment, admins can apply it manually from the Business Central administration center. If the
update has not been applied to an environment by the specified last update date, Microsoft will auto-apply the
update. Microsoft takes into account the update window for the environment.
Example release schedule
The following figure illustrates the key milestones and dates for rolling out a minor update in any month.

The following table describes the milestones with example dates for a minor update in any given calendar year.

M IL ESTO N E EXA M P L E DAT E DESC RIP T IO N

Update is available May 07 The date when the new minor version
of Business Central is first available and
admins can schedule the update.

Update rolls out automatically May 14 The default date when Microsoft starts
upgrading your environments, 7 days
after the first availability date. Once
the update is scheduled, you can
change that date, within the allowed
date range, to a date that suits you
better.

Last scheduled update date May 28 The last date you can choose to extend
your upgrade date to, 21 days after
the update is available.

TIP
The minor updates tend to become available on the first Friday of any given month, except the months when a major
update becomes available. Microsoft aims to update the last environments 2-3 weeks later.
Update availability
The major updates are typically made available twice a year, in April and in October. Minor updates roll out every
month. Get an overview of the release plans at Dynamics 365 and Microsoft Power Platform release plans. For
Business Central release plans, select a release wave under Dynamics 365 , then look under SMB in the table of
contents.
On the release day for any update, all new sign-ups and all newly created environments (sandbox and
production), are directed to the new version. For existing environments that run on the previous version,
updates are made available gradually across the supported regions over the coming days and weeks as
indicated earlier in this article. It's not possible to speed up this process for your environment through Microsoft
Support.

Schedule updates
When the update becomes available for your environment, a notification email is sent to all notification
recipients that you've registered in Business Central administration center. A notification about the update
availability is also shown in the Business Central administration center itself.
Starting this day, you can use the Business Central administration center to schedule the date when you prefer
the update to happen.
The following fields on the environment page can help you plan the update:

F IEL D DESC RIP T IO N

Available Update Version Specifies the version to which you can update your
environment

Update Scheduling Available Specifies whether it's possible for you to change the update
date. The options are Yes or No .

Scheduled Update Date Specifies the default update date set by Microsoft. You can
change this date to one you prefer, if Update Scheduling
Available is set to Yes

Update Window (UTC + offset) Specifies the hours of the day that an update can run. (UTC
+ offset) indicates the time zone, represented as
Coordinated Universal Time plus or minus the difference in
hours and minutes.

Update Rollout State Microsoft can sometimes postpone the updates for various
reasons. This field provides information that can help you
track the current state of the rollout. For more information
about what happens in such cases, see Postponed updates

IMPORTANT
If you don't set a date in the Scheduled Update Date field, Microsoft will update the environment automatically on any
day between the default date and the date that is shown as the last possible update date in your notification email. If you
don't want your environment to be updated automatically, change the update date to one that fits you better.

When the scheduled update date arrives, the update runs automatically within the update window that you've
specified for this environment. All users will be disconnected from this environment, and all attempts to sign in
during the update will be blocked with the message Service is under maintenance .
IMPORTANT
We strongly encourage that you set an update window for all production environments so that updates don't start
during business hours.

For more information, see Set the update window for each environment.

NOTE
When you select a current date for your update, but the update window defined for this environment has already passed,
the update will start within that time window, but on the day after the one that you defined for your environment.
For example, if you're changing the Scheduled update date to the current date at 6 PM, and your update window is
set to 1 AM - 7 AM, the update will not start immediately, but after 1 AM on the next day.

Delayed scheduling of updates


In some cases, even after the update is available in your area, you are still not be able to set the update date
(schedule environment update). This condition can happen for one of the following reasons:
Your environment hasn't yet updated to the latest minor update of the previous version of Business
Central. All environments must be updated to the last available minor update of the previous version of
Business Central before they can be scheduled for the next major version. You can check the version
information in the Troubleshooting section of the Help and Suppor t page in Business Central and in
the Version Management section in Business Central administration center. For more information, see
Version numbers in Business Central.
Microsoft actively works on updating all environments to the latest minor update as soon as possible. In
most cases, your environment will be scheduled for the major update soon. You'll get a chance to change
the date to the one that fits you better. In the unlikely situation that your environment is updated to the
last minor update around or even after the last selectable update date, you'll still get at least seven days
to schedule the update.
You've just created a new sandbox environment as a copy of your production environment. In this case,
the sandbox environment is created on the same version as the production environment it was copied
from. If your newly created sandbox environment is running on the last minor update of the previous
version, Microsoft will schedule it for update automatically within one hour.
You'll receive email notification and will see the notification in Business Central administration center
when it happens. The scheduled update date for this environment will be set to seven days from the
current date. This gives you enough time to change the date to one that fits you better, including the
current date.
Your per-tenant extensions aren't compatible with the next major update.
Before a major update, Microsoft routinely checks per-tenant extensions in all existing environments for
compatibility with the next major update. If we detect compatibility issues with the upcoming version, we
send email notifications that describe the detected issues to the notification recipients. We warmly
encourage all admins to review these emails and take action as soon as possible.
Ifyou discoverany such issues, apply the changes to your solution as usual using Visual Studio Code. Test
the new appin a sandbox environment that runson the new major version, either in preview or the official
version. If testscomplete successfully, upload the new app version into your production environment in
the Extension Management page, setting theDeploy to field toNext major version .This way the
compatible version of your app will beusedwhenyour environment is updated.For more information, see
Deploying a Tenant Customization.
The AppSource apps that are installed in your environment aren't yet available for the next major version
of Business Central.
While most AppSource apps are kept up to date by the app providers, a particular app might need more
time to prepare for the next major update and isn't yet available for it. In this situation, contact the app
owner to understand their availability plans.

TIP
Make sure each environment has the right contacts set up t get email notification. For more information, see Managing
Tenant-Specific Notifications.

Failed updates and rescheduling


An environment may fail to update for various reasons, such as the following:
Per-tenant extension compatibility issues
AppSource app compatibility issues
Internal update issues
Any environment that fails to update will be automatically restored to the original application version so that
users can connect to it again. The environment is then automatically rescheduled for a new update attempt in
seven days. If you consider the issue resolved and want to try the update again, change the update date to an
earlier date or the current date.
If Microsoft can't do the update on the selected date, you'll be notified by email that the environment update is
rescheduled for seven days later. You can change that date in the Business Central administration center to any
other allowed date, including the current date.

Postponed updates
In critical circumstances, Microsoft can decide to postpone the rollout of the updates, such as if a critical issue is
discovered in the upcoming major version. While Microsoft is working on addressing the issue, the updates will
be postponed. You'll receive email notification, and you'll see the notification displayed in the Business Central
administration center. The Version Management section for each environment will show the update rollout
state as Postponed.
If we do not know the nature of the issue and the solution in advance, we can't predict when the updates will
resume again. As a result, neither the email nor the notification in Business Central administration center will
contain the information about the expected resume date. In these extreme cases, Microsoft actively works on
resuming updates as a matter of highest priority once the issue is addressed. You'll receive another email
notification when updates have resumed. The last available date will be prolonged by the number of days that
the update was postponed.
If it happens that you schedule the update of an environment to a date when the updates are postponed, the
environment will not be updated. Microsoft will not send separate notification. You can reschedule the update to
a later date, or you can wait until you have received the email notification that the updates have resumed. All
environments that missed their scheduled update date will be rescheduled automatically to run the update
within seven days from the date the updates were resumed. You can change that date to any other allowed date,
including the current date.
If you didn't explicitly set a date for your environment update in the Business Central administration center, this
environment will be picked up for updating automatically, shortly after the updates have been resumed. The
update will still be executed within the specified update time window.
Prepare, test, and learn before a major update
You can prepare yourself, users, and any customizations by trying out the new major version before your
production environment is updated. The following sections provide recommendations for how to prepare for an
update.

IMPORTANT
We strongly recommend that you test any critical business scenarios before your production environments are updated
to the new major or minor version.

Prepare for major updates by enabling select features earlier


Some new features can be switched on ahead of time on sandbox and production environments, giving you
time to test and prepare for change. Most times, you can switch on features several weeks before preview
environments for the major update are available.
When Microsoft releases features or feature design improvements as part of minor updates, some of these
features are optional until the following major update. Administrators can turn these optional features on or off
from the Feature Management page.
For more information, see Feature Management.
Prepare for major updates with preview environments
About one month before a major update, you can try out new functionality in preview environments. Preview
environments are Business Central online sandbox environments that you create on a preview version of the
application. When you create the new sandbox environment, choose the preview version marked as (Preview)
from the version list. This way, you get a new sandbox environment with a preview version of the application.
Use Microsoft Collaborate to submit your feedback or to report any potential issues that you discover in the
preview. For more information about getting access to Collaborate, see Step 4 in the readiness section for
developers.

NOTE
Previews roll out gradually across the world, so if the option is not showing up for you today, please try again tomorrow.

The newly created preview sandbox environment contains demonstration company data. Trying the preview on
a copy of your current production data is not yet supported; nor is testing the upgrade from your current
version to the preview. However, you can use the newly created sandbox environment for exploring and learning
the new product capabilities. You can also use the preview environment to validate that any per-tenant
extensions are still working as expected.
If you run your tests on a preview environment one month before the announced major release of Business
Central, it is more likely that the coming updates of your production environments will go smoother. This way,
you, your customers, and your code are better prepared for the official release.
We expect to update the preview version only if we discover critical issues before the major update is generally
available for production environments. Apart from these potential fixes, we do not expect any further changes to
the product between the preview and the official release. You can start your testing and learning activities
immediately, without waiting for the official release.
NOTE
You will be able to test the update on a copy of your production data in a sandbox environment when we release the new
update in production in April or October, respectively. When the official release becomes available, you can continue your
tests on that version. You will no longer be able to create new preview sandboxes.

IMPORTANT
The preview version as well as all sandbox environments that are based on it will be removed 30 days after the official
release becomes available.

For more information, see Prepare for major updates with preview environments.
Prepare for major updates just before the production environment is updated
As soon as you're notified that the new major update is available, you can test the new version. Just create a
sandbox environment that you then schedule to be updated. Start by copying your production environment into
a sandbox on the same version as your production environment. All newly created environments are
automatically included in the update process within one hour. You'll get notified that the update is available, and
you'll be able to schedule the newly created sandbox for update within one hour after it was created. By default,
the newly created environments are scheduled to run the update within seven days from the date they were
created, but you can change that date to any other allowed date, including the current date.
If you change the update date to the current date, the update will start within the closest available update time
window you specified for the environment. If you want to start the update of your sandbox environment
immediately, you can set the update time window for this sandbox environment to be 24 hours.
Microsoft monitors each update of an environment. If we detect any errors during the update, you'll receive
email notification that describes the detected issues.
Any environments that fail to update due to per-tenant extension compatibility issues or any other issues are
automatically restored to the original application version. Within one hour, they are automatically rescheduled
for another update attempt. The scheduled update date is automatically set to seven days in the future to give
you time to resolve the issues. If you address the compatibility issues sooner, you can change the date to an
earlier date, including the current date. This pattern repeats until the environment is updated successfully.

IMPORTANT
Changing date to an earlier date might be blocked up to 24 hours after the last failed attempt to update.

Overview of the timeline for preparing for the next major update
The following figure illustrates the suggested steps for getting a preview of a major update with example dates
for the two release waves in any given calendar year.
The following table provides more information for the suggested steps with example dates for the two release
waves in any given calendar year.

M IL ESTO N E EXA M P L E DAT E WAVE 1 EXA M P L E DAT E WAVE 2 DESC RIP T IO N

Previews are available March 1 September 1 You create a new sandbox


environment based on the
new preview for test
purposes. For more
information, see Prepare for
major updates with preview
environments.

A few days before you March 31 September 30 You create a new sandbox
know that the update is environment based on your
announced existing production
environment (copy your
production environment
into a sandbox) and wait for
it to be updated to the new
version.

Update available in your April 6 October 5 The major update is made


region available. You're notified
about it via e-mail. Go to
the Business Central
administration center and
set the update date for
your sandbox environment
to the current date. The
sandbox will be updated
within the closest available
update time window that
you set for it. Now, you can
test your existing
extensions and your
production data against the
new version.

We recommend that you


set the update date for
your production
environment a few days or
weeks in the future, to help
make sure that it does not
get updated automatically
before you had a chance to
test the new version and
your extensions in your
sandbox environment.

Preview sandboxes are May 1 November 1 30 days after the new major
deleted update is announced, the
preview sandboxes are
deleted. There will be no
option to keep these
sandboxes or export data
from them.

Service updates
The service components apply to multiple environments, such as all tenants in a region. So Microsoft schedules
those updates to a time when traffic is lower in each region, typically during the evening or night. Typically, these
service updates are transparent to any users, as the service is designed to manage traffic in a way that any users
still working in Business Central are not affected by these service updates.
These updates do not add or remove functionality, and they are transparent to business users.

See also
Managing Major and Minor Updates of Business Central Online
Working with Administration Tools
The Business Central Administration Center
Managing Environments
Managing Tenant Notifications
Introduction to automation APIs
Version numbers in Business Central
2/6/2023 • 2 minutes to read • Edit Online

Business Central online and on-premises consists of different components that must work together. If you are a
an enduser, this doesn't matter in the course of your normal work day. But if you are an administrator, knowing
the version numbers is important for troubleshooting, development, and on-premises upgrade scenarios.
You can use the information about which version the tenant is on to help you troubleshoot an issue that a user
has reported, for example. This information is listed in the Troubleshooting section of the Help and Suppor t
page in Business Central in the following format:

VERSIO N EXA M P L E DESC RIP T IO N

Platform <major>.<minor>.<build>. 20.0.12345.0 Specifies the full platform version,


<revision> which includes client and server
components.

Application <major>.<minor>. 20.1.23456.0 Specifies the full version number for


<build>.<revision> the application, including the major
version number and build number.

In the Business Central administration center, the version information is rendered slightly differently:

VERSIO N EXA M P L E DESC RIP T IO N

Platform <major>.<minor> 20.1 Specifies the major and minor version


of the platform, which includes client
and server components.

Application <major>.<minor>. 20.1.23456.0 Specifies the full version number for


<build>.<revision> the application.

The numbers are updated based on Microsoft's builds. In the default version of Business Central online, platform
and application have the same major version number but different build numbers. If you perform a technical
upgrade of Business Central on-premises, then platform and application will have different versions.
The following list describes the meaning of each of the numbers in a full version number:
major is the major version of Business Central
20 is the Business Central 2022 release wave 1 update in April 2022 and forward
19 is the Business Central 2021 release wave 2 update in October 2021 and forward
18 is the Business Central 2021 release wave 1 update in April 2021 and forward
17 is the Business Central 2020 release wave 2 update in October 2020 and forward
16 is the Business Central 2020 release wave 1 update in April 2020 and forward
15 is the Business Central 2019 release wave 2 update in October 2019 and forward
14 is the Business Central April 2019 release
13 is the Business Central October 2018 release
12 is the April 2018 launch of Business Central
minor is the monthly update number, such as 0, 1, or 5.
build is the five digit build number, such as 23456.
revision is set to 0 for the original release and can remain at 0. However, if the tenant is patched with a
hotfix, then that build number can be applied.
In other words, if you see a version number such as 20.1.23456.26323 , then it means major version 20, update
number 1, build number 23456, and hotfix number 26323.
The same version numbers are used to identify versions in Business Central on-premises, including when you
deploy containers on Docker.

See Also
Managing Technical Support
Installing a Cumulative Update
Administration of Business Central Online
Operational Limits for Business Central Online
2/6/2023 • 7 minutes to read • Edit Online

To ensure the availability and quality of Business Central services, there are limits on certain operations. This
article describes the limits and, in some cases, the strategy behind them.

TIP
Telemetry is gathered on some of the operations that have a limit. The telemetry provides insight into operations for
which limits were exceeded. For more information, see Monitoring and Analyzing Telemetry.

Client connection limits


SET T IN G DESC RIP T IO N L IM IT

Reconnect period The time during which a client can 10 minutes


reconnect to the service after being
disconnected.

Data handling limits


SET T IN G DESC RIP T IO N L IM IT

Max items in object graph The maximum number of objects to 10,000


serialize or deserialize.

Max file size The maximum size of files that can be 350 MB
uploaded to or downloaded from the
service.

Maximum stream read size The maximum number of bytes that 1,000,000 bytes
can be read from a stream (InStream
object) in a single AL read operation.
Examples include READ or
InStream.READTEXT method calls. This
setting pertains to UTF-8 and UTF-16
text encoding; not MS-DOS encoding.

Database limits
SET T IN G DESC RIP T IO N VA L UE

Search timeout The time (in seconds) that a search 10 seconds


operation on lists in the client
continues before it's stopped. When
the limit is reached, the following
message displays in the client:
Searching for rows took long and
was stopped. Tr y to search or
filter using different criteria.
SET T IN G DESC RIP T IO N VA L UE

SQL command timeout The contextual time-out for a SQL 30 minutes


command.

SQL connection idle timeout The time that a SQL connection can 5 minutes
remain idle before being closed.

SQL connection timeout The time to wait for the service to 1.5 minutes
connect to the database. When the
time is exceeded, the attempt is
canceled and an error occurs. This
setting also applies to begin, rollback,
and commit of transactions.

Long running SQL query threshold The amount of time that an SQL query 1000 ms
can run before a warning telemetry
event occurs. If this threshold is
exceeded, the following event is
logged: Action completed successfully,
but it took longer than the given
threshold.

Asynchronous task limits


SET T IN G DESC RIP T IO N L IM IT

Background sessions default wait The maximum amount of time that 8 hours
timeout background sessions will wait to be
processed.

Background sessions max concurrent The maximum number of background 10


sessions per tenant that the server
instance can actively process at the
same time. Requests that exceed the
limit will wait in the queue until a slot
becomes available.

Background sessions max queued The maximum number of background 100


sessions per tenant that can be waiting
to be processed.

ChildSessionsMaxConcurrency The maximum number of child 5


sessions that can run concurrently per
parent session. When the value is
exceeded, additional child sessions will
be queued and run when a slot
becomes available as other child
sessions are finished.

Child sessions max queue length The maximum number of child 100
sessions that can be queued per
parent session. If the value is exceeded,
an error occurs.
SET T IN G DESC RIP T IO N L IM IT

Maximum concurrent running The maximum number of tasks that 3


scheduled tasks can run simultaneously for an
environment.

If there are many jobs running at the


same time, you might experience that
the response time for clients gets
slower. If the value is too low, it might
take longer for scheduled tasks to
process.

Maximum session recursion depth The maximum number of nested 14


sessions that can be created before
reaching infinite recursion. If the limit is
exceeded, a runtime error occurs with
the message: Excessive recursive
session creation detected,
original session ID: [id], current
session ID: [id].

Page background task default timeout The default amount of time that page 2 minutes
background tasks can run before being
canceled. Page background tasks can
be also given a timeout value when
enqueued at runtime. This limit is used
when no timeout is provided when the
page background task is enqueued.

Page background task max timeout The maximum amount of time that 10 minutes
page background tasks can run before
being canceled. Page background tasks
can be also given a timeout value
when enqueued at runtime. If a page
background task is enqueued with a
timeout greater than this limit, this
limit is ignored.

Report limits
SET T IN G DESC RIP T IO N L IM IT

Default max documents The maximum number of documents 200


that can be merged in a report using a
Word layout. Users can override this
setting on a report-basis from the
report request page. If exceeded, the
report will be canceled.

Developers can override this setting by


using MaximumDocumentCount
property of a report. Client users can
do the same when running a report
from the report request page
SET T IN G DESC RIP T IO N L IM IT

Max documents The maximum number of documents 500


that can be merged in a report using a
Word layout. If exceeded, the report
will be canceled.

Default max execution timeout The maximum execution time that it 6 hours
can take to generate a report by
default. Users can override this setting
on a report-basis from the report
request page. If exceeded, the report
will be canceled.

Developers can override this setting by


using the ExecutionTimeout property
of a report. Client users can do the
same via Repor t Limits page, or
when running a report from the report
request page as a one-time change.

Max execution timeout The maximum execution time that it 12 hours


can take to generate a report. If
exceeded, the report will be canceled.

Default max rows The maximum number of rows that 500,000


can be processed in a report by
default. Users can override this setting
on a report-basis from the report
request page. If exceeded, the report
will be canceled.

Developers can override this setting by


using the MaximumDataSetSize
property of a report. Client users can
do the same when running a report
from the report request page.

Max rows The maximum number of rows that 1,000,000


can be processed in a report. If
exceeded, the report will be canceled
by the server.

Query limits
SET T IN G DESC RIP T IO N L IM IT

Max execution timeout The maximum execution time that it 30 minutes


can take to generate a query. If
exceeded, the query will be canceled.

Max rows The maximum number of rows that 1,000,000


can be processed in a query. If
exceeded, the query will be canceled.

Company limit (per environment)


SET T IN G DESC RIP T IO N L IM IT

Max companies The maximum number of companies 300


that can be contained in one
environment.

TIP
This company limit will take effect in 2023 wave 1 release. When in effect, exceeding the limit will prevent you from doing
some environment operations. For information about the consequences of exceeding the limit, go to Operational
challenges with many companies per environment.
If you already have more than 300 companies in one environment, distribute them across more environments to avoid
problems later.

OData request limits (per environment)


SET T IN G DESC RIP T IO N L IM IT

Max body size The maximum request body size. 350 megabytes

Max concurrent requests The maximum number of OData V4 5


requests the server instance can
actively process at the same time.
Requests that exceed the limit will wait
in the queue until a time slot becomes
available.

Max connections The maximum number of simultaneous 100


OData requests on the server instance,
including concurrent and queued
requests. When the limit is exceeded, a
429 (Too Many Requests) error occurs.

Max page size The maximum number of entities 20,000 entities per request
returned per OData request.

Max batch size The maximum number of operations in 100 operations per batch
an OData $batch request.

Max request queue size The maximum number of pending 95


OData V4 requests waiting to be
processed. When the limit is exceeded,
a 429 (Too Many Requests) error
occurs.

Rate The number of OData requests per Sandbox:


minute that are allowed. An HTTP 300 requests/minute
response code
429 - Too Many Requests is Production
returned if limits are exceeded. - 600 requests/minute
SET T IN G DESC RIP T IO N L IM IT

Operation timeout The maximum amount of time that the 8 minutes


service gives a single OData request.
When the limit is exceeded, an HTTP
response code
408 - Request Timeout is returned.

After 8 minutes, the session is


canceled.

Max number of webhook subscriptions The maximum number of Webhook 200


subscriptions.

SOAP request limits (per environment)


SET T IN G DESC RIP T IO N L IM IT

Max concurrent requests The maximum number of SOAP 5


requests the server instance can
actively process at the same time.
Requests that exceed the limit will wait
in the queue until a time slot becomes
available.

Max connections The maximum number of simultaneous 100


SOAP requests on the server instance,
including concurrent and queued
requests. When the limit is exceeded, a
429 (Too Many Requests) error
occurs.

Max message size The maximum permitted size of a 65,536 KB


SOAP web service requests

Max request queue size The maximum number of pending 95


SOAP requests waiting to be
processed. When the limit is exceeded,
a 429 (Too Many Requests) error
occurs.

Rate Specifies how many SOAP requests per Sandbox:


minute are allowed. An HTTP response 300 requests/minute
code 429 - Too Many Requests is
returned if limits are exceeded. Production:
600 requests/minute

Operation timeout The maximum amount of time that the 8 minutes


service gives to a single SOAP request.
When the limit is exceeded, HTTP
response code
408 - Request Timeout is returned.
TIP
Throttling will happen when many requests are issued at the same time. If requests are taking a long time to complete,
throttling might also occur due to the request queue being filled up. To optimize throughput, ensure to use APIs or
OData over SOAP, as they execute faster.

See Also
Working with API Rate Limits
Microsoft API Terms of Use
Technical Support for Dynamics 365 Business
Central
2/6/2023 • 5 minutes to read • Edit Online

Each customer of Business Central has a partner who assists with technical support. As a Business Central
reselling partner, you are an administrator of your customers' Business Central tenants, and you are the first line
of support. You will get requests for support from your customers that you must triage, investigate, and either
resolve or escalate to Microsoft.
In this section, you can learn about the tools that are available to you to help you troubleshoot your customers'
Business Central.

Configuring the support experience


Because you are the first line of support for your customers, you must make it easy for them to contact you.
They can find your contact information in the Help and Support page.

IMPORTANT
You must have set up users in your own tenant in Partner Center as either Admin agent or Helpdesk agent, and they
must have delegated administration privileges in your customer's Business Central to support the customer. For more
information, see Delegated Administrator Access to Business Central Online.

To supply your support contact information in the administration center


1. In the Business Central administration center, choose the environment that you want to specify your contact
details for, such as Production, and then, in the Suppor t menu, choose Manage Suppor t Contact .
2. Fill in the Name , Email address , and the Website fields, so that your users know how to contact you for
technical support.
3. Optionally, choose the Apply to all environments checkbox if you want to add the same details to all
related environments for this tenant.
Your customer can now contact you if they experience problems and need help. If you also cannot resolve a
reported issue, escalate the issue to Microsoft. For more information, see Managing Technical Support.
On-premises deployments
In on-premises deployments of Business Central, the Help and Suppor t page does not contain the section for
contacting technical support. Instead, you can enter an agreement with your customer's administrator about
how and when to contact you.
There are two other links in the Help and Suppor t page that you can customize:
Blog
Specifies a link to where your customers can access a blog about their solution
Coming soon
Specifies a link to where your customers can access a roadmap for future changes
If you choose to not modify these settings, then the links go to Microsoft's blog and release notes.
For more information, see Configuring Business Central Web Server Instances.

Getting support for extension issues


As a partner, you must identify if the issue is caused by application logic or platform behavior:
If the issue is caused by application logic, you must identify the publisher of the extension.
If the extension is a per-tenant extension, as a partner, you must fix the issue.
If the extension is an AppSource extension, you must contact the AppSource partner that developed the
extension.
If the extension is published by Microsoft, you must contact Microsoft support.

Troubleshooting and support


The Business Central administration center is your primary tool to support your customers. However, you can
also sign in to the customer's Business Central as the delegated admin for troubleshooting.
For more information, see Managing Technical Support.

Monitor service health


Both as an internal admin and as a delegated admin, you can help users determine the cause of their problems
in different ways before you have to escalate the issue to Microsoft Support. The starting point is the Business
Central administration center where you can access telemetry for the tenant and check the status of already
reported outages. For more information, see Managing Production and Sandbox Environments in the Admin
Center.
The Microsoft 365 admin center provides an overview of service health across Microsoft services. Select
Preferences to receive service health email notifications about incidents across Business Central, Microsoft
365, and other Microsoft services. For more information, see How to check service health. If you manage more
than one tenant, see View service health for all accounts.
As a partner, use the Partner Center to get an overview of service health for each customer. For more
information, see Check service health for a customer in the Partner Center content. You can also use APIs for
automated service notifications for Azure Insights & Office 365 service communications.
Summary of where to file bugs and issues
As a partner, you have different support channels depending on what type of issue you want support for. The
following list outlines the various channels.

ISSUE T Y P E SIT E

Submit support request on behalf of your Business Central Start at the Business Central administration center where
online customers you can easily submit a support request in the Power
Platform admin center

Report bug in a preview or beta version The MS Collaborate site

Collaboration on the AL language and developer experience The AL Developer Preview GitHub repo

As an ISV, report an issue in production code, such as a The Partner Center Support site - choose the Marketplace
problem with Microsoft's application, upgrade, or telemetry Offers category, and then choose the relevant category in
the Problem type field, such as Dynamics 365 Business
Central Development > Core Application issues. You'll be
asked to check resources and then to provide issue details.
ISSUE T Y P E SIT E

Report bug in supported in-market versions of Business The Support for business site
Central on-premises

IMPORTANT
To submit support requests on behalf of your customer, you must be a delegated admin on the customer tenant. Your
company must also have the Advanced or Premier support plan. For more information, see the Escalating support issues
to Microsoft section.

TIP
When you submit your first support ticket as a partner, you must specify details about your company's support plan. If
you or your colleagues do not know these details, contact your Microsoft rep.

Non-product related questions


On occasion, as a partner, you will run into questions that are not directly related to the product. The following
list outlines how to get answers to those questions.

F O R Q UEST IO N S REL AT ED TO C O N TA C T

Problems with listing or publishing apps to AppSource due The Partner Center Support site - choose the Marketplace
to Commercial Marketplace issues offers category, and then choose the relevant category in
the Problem type field, such as Availability > Dynamics
365 Business Central offer.

Licensing or PSBC agreements Email MBS Orders or MBS Agreements, respectively

Microsoft Partner Network, Partner Center, Cloud Solution The Partner Center Support site
Provider program

Payments, credit terms, checks, wire, or similar Email MBS Accounting

Technical issues with PSBC, PartnerSource, or Order Central Email IT MBS Support

Incentives Email CSA Team

Cloud Solution Provider incentives Email Online Channel Incentives Support

CSA/Ocina escalations Email NAOC Channel Incentives Escalations

Volume licensing The Call Logging Tool site or email Online Licensing

See Also
Inspecting and Troubleshooting Pages
The Business Central Administration Center
Managing Technical Support
Deployment Overview
Administration of Business Central Online
Administration of Business Central On-Premises
Provide technical support (Microsoft Partner Center)
Providing support to your customers (Microsoft Partner Center)
Production and Sandbox Environments
2/6/2023 • 11 minutes to read • Edit Online

You can create environments of different types. Which type of environment to choose depends on what you
need it for.

TIP
If you're new to environments, get an overview of how Azure Active Directory, environments, and companies work in
Business Central online at Understanding the infrastructure of Business Central online.

Production environments
Production environments are meant to be precisely that: Environments that a business can run their daily
business in Business Central in, deployed on performance tiers in Azure with a guaranteed high level of
availability and support.
Production environments are backed up automatically and frequently to help protect business data. For more
information, see How often are production databases backed up?.
You can create additional production environments for training or performance testing, for example. However,
for training purposes, in many cases organizations will prefer to create a sandbox environment with production
data. You can also create additional production environments to support offices in different countries.

NOTE
The Premium and Essential subscription types give each Business Central customer one production environment and
three sandbox environment free of extra charge. If the customer requires more production environments, they can buy
additional environments through their CSP partner. Each additional production environment comes with three additional
sandbox environments and 4 GB additional, tenant-wide database capacity. In addition, starting in 2023 release wave 2,
there's a limit on how many companies you can have on a single tenant (see Operational limits).

Administrators can create the additional environments in the Business Central administration center. The
environments can be created and used in any country or region where Business Central is available, including
the countries or regions where the customer's existing environments are running. The environments quota is
applied when you try to create a new environment, or copy an existing environment, in the Business Central
administration center.

NOTE
A production environment can have a state of suspended if the subscription has been suspended, or if the environment
has not been accessed for a long time. In those cases, you can only publish extensions to such an environment if it only
has evaluation companies. If the suspended environment has been used for actual production so that it contains
companies that are not evaluation companies, then you cannot publish extensions to it.

Manage production environments


Use the Business Central administration center to manage the environments manually. For more information,
see Managing Production and Sandbox Environments.
Instead, use the Administration Center API.
Sandbox environments
Sandbox environments are meant to be precisely that: Environments that you can play around with, use as a
testbed for development, and delete at will. You can deploy apps straight from Visual Studio Code to a sandbox
environment, and you can attach a debugging session to a sandbox.

IMPORTANT
Apps that are published to a sandbox from the development environment or created using Designer are published within
the scope of the service node that hosts the environment. When the sandbox is upgraded, these apps are removed
because the environment is moved to another node that is running the new version. However, the data of the app is not
removed, so you only have to re-publish and install the app to make it available.
Apps that are uploaded to the environments of both types (production and sandbox) using the Upload Extension
action from the Extension Management page are published within a global scope. When the environment is upgraded
or moved, these apps are downloaded to the service node and installed, which means that they will not disappear.

You can also safely use sandboxes for training, such as for following a learning path from Microsoft Learn,
because it's a safe environment to experiment with. If anything goes wrong, you just delete the sandbox and
start over.

IMPORTANT
The automatic backup that applies to production environments does not apply to sandbox environments. If you want to
export data from a sandbox environment, you can use Excel or RapidStart, but you cannot request a database export.

You can create a sandbox environment that includes data from your production environment for debugging
purposes, for example. But if you want to run performance tests, or similar benchmarking, the sandbox is not
reliable enough for that purpose. This is because sandboxes run in a different performance tier on Azure than
production environments. Instead, create a dedicated environment based on the Production environment type -
this gives you the exact experience and performance that users will experience in the actual production
environment.
Sandbox environments are handy for certain types of development scenarios because the debugging endpoint
is open by default. This means that you can attach Visual Studio Code to a running system and debug through
running code. It also allows you to publish directly to the environment from Code.
If your organization has more than one sandbox environment, you can switch between environments by
opening the App Launcher, choosing the Dynamics 365 tile, then choose the Business Central Sandbox tile. The
sandbox environment picker shows the available sandboxes, so choose the one that you want to switch to.

NOTE
The Premium and Essential subscription types give each Business Central customer one production environment and
three sandbox environment free of extra charge. If the customer requires more production environments, they can buy
additional environments through their CSP partner. Each additional production environment comes with three additional
sandbox environments and 4 GB additional, tenant-wide database capacity. In addition, starting in 2023 release wave 2,
there's a limit on how many companies you can have on a single tenant (see Operational limits).

Administrators can create the additional environments in the Business Central administration center. The
environments can be created and used in any country or region where Business Central is available, including
the countries or regions where the customer's existing environments are running. The environments quota is
applied when you try to create a new environment, or copy an existing environment, in the Business Central
administration center.
Partner sandboxes
As a partner, you can buy the Dynamics 365 Business Central Partner Sandbox license. You'll need a valid
Microsoft Partner Network (MPN) ID. You must also have at least five employees who will use the partner
sandboxes that you create using this license. This offer was made available in February 2022 to support
partners that need non-production environments to learn, test, and deliver end-to-end customer demos with
their solutions. The Partner Sandbox license gives access to Business Central Premium functionality.

IMPORTANT
The environments that you acquire through the Dynamics 365 Business Central Partner Sandbox license are strictly
meant for use only on the partner’s tenant. You are not allowed to use this license in a customer tenant, nor in a
production environment.

Use the Partner Sandbox license for an Microsoft 365 account that does not currently have a Business Central
license. This gets you 1 production environment + 3 sandboxes. Alternatively, use the Partner Sandbox license to
replace existing Business Central licenses in an existing environment; however, the license will not give you any
additional environments on top of the environments you already had.
Partners can purchase the unique, partner-only license via Web Direct to create flexible, cost-effective solutions
that do not expire. Accessing the SKUs and pricing is simple: Go to experience.dynamics.com and submit a
request for the Dynamics 365 Business Central Partner Sandbox license. Use a valid MPN ID. Once your request
is approved, you receive a token to purchase the SKUs directly. Pay by credit card. If the total billing is over
$500/month for your company, then you can pay by invoice.
Precautions for sandbox environments with production data
When an environment is created as a copy of another environment, a number of precautions are taken for that
copy:
Tasks in the job queue are automatically stopped
To see which scheduled jobs are stopped, and to decide which jobs to restart in the new environment, go
to the Scheduled Tasks page in Business Central. There, you can set tasks to be ready to run in the job
queue. However, only tasks that are marked as belonging to the current environment can run. For more
information, see View Scheduled Tasks in the business functionality content.
Any base application integration settings are cleared
Any irreversible features that were enabled in the original environment will also be turned on in the copy.
For more information, see Features that can't be turned off.
Development extensions that are published from AL-Go for GitHub or Azure DevOps and any extensions
that depend on them are uninstalled when the source environment is a sandbox. Any data that was
created in the original environment by the extensions that are now uninstalled in the copy will not be
deleted. Any updates to per-tenant extensions that are slotted to be upgraded with the next minor or
major upgrade will be retained.
Outbound HTTP calls from extensions are blocked by default and must be approved for each extension,
otherwise instead of an external call, the system will display the following error message: The request
was blocked by the runtime to prevent accidental use of production services.
To enable outbound HTTP calls, go to the Extension Management page in Business Central, and choose
Configure . Then, on the Extension Settings page, make sure that Allow HttpClient Requests is
selected. This setting must be enabled for each extension, including libraries.
Any General Data Protection Regulation (GDPR) action must be handled separately and repeated for the
environment. There is no synchronization with the original environment after the copy has been created.
The internal administrator has the same tools and responsibilities for the copy as they do for the original
environment. As a data processor, Business Central offers the same level of data protection and data
handling restrictions to all types of environments, both sandboxes and production environments.
The following setups are set to status disabled
Doc. Exch. Service Setup
Curr. Exch. Rate Update Setup
VAT Reg. No. Srv Config
Graph Mail Setup
CRM Connection Setup
CDS Connection Setup
All records in the Service Connection table
All records in the Exchange Sync table
The following data is cleared
Password in the OCR Service Setup table
SMTP Server in SMTP Mail Setup
Exchange Service URL in the Marketing Setup table
The following changes are made for first-party extensions
AMC Banking 365 Fundamentals
The Service URL in AMC Banking Setup is reset to default for Sandbox environments
Email - Outlook REST API
All email accounts of types "Microsoft 365" and "Current User" are deleted. Deleting these
records turns any existing field monitoring setup non-valid.
Email - SMTP Connector
SMTP Server details are deleted
The following changes are made for specific localizations
Spain
SII Setup is set to disabled
United Kingdom
Password in GovTalk Setup table is deleted
Netherlands
All Digipoort related fields in the Elec. Tax Declaration Setup table are cleared
Manage sandbox environments
Use the Business Central administration center to manage the environments manually. For more information,
see Managing Production and Sandbox Environments.
Alternatively, use the Administration Center API.
Pre -sales performance evaluation
If you want to provide a prospect with an online environment where you want to demonstrate the performance
and reliability of Business Central online in addition to demonstrating functionality, you must take a few extra
steps.
To demonstrate the functionality of the default version of Business Central, without focusing on performance,
you can quite simply use your own trial experience based on a Microsoft 365 demo account. We recommend
that you show the full functionality of the default version by switching the tenant to the 30 day trial and the
associated My Company. You can then enable the Premium user experience in the new My Company's
Company Information page, populate the new company with the data required for their evaluation scenarios,
and present the environment to the prospect.
To demonstrate the functionality of the service, with a focus on performance, you can take the same step as
outlined above, but then also sign up the prospect for the Business Central Premium Trial offer that is available
through your CSP access in the Partner Center, wait 24 hours, and then run your performance evaluation. For
more information, see Preparing Test Environments of Dynamics 365 Business Central.
That 30 day trial is as close to an actual production environment performance as you can get. You only have
those 29 days to run your tests and convince the prospect, of course, but provided that you have prepared
everything in advance, it should give you time enough.
If the prospect is convinced and decides to buy Business Central, you can then either let them keep the
environment that they are currently using, or create a new production environment for them. If the tenant is
yours rather than the prospect's, then a new tenant will be provided to them.
For more information about performance and Business Central, see Performance Overview.
Advanced user experience
It is possible to enable and try the full functionality of the standard version of Business Central in a sandbox
environment by setting the Experience field on the Company Information page to Premium. Find the
Company Information page in the menu in Business Central. However, we recommend that you as the
admin set up dedicated demonstration environments instead. For more information, see Preparing
Demonstration Environments.
Complete sample data
The standard demonstration company in Business Central includes sample data for a limited number of
scenarios. You can also create a new company with the Advanced Evaluation - Complete Sample Data
option. In this type of company, users can take training or step through walkthroughs that require more sample
data, such as Walkthrough: Receiving and Putting Away in Basic Warehouse Configurations. This sample data is
different from the standard sample data, and we advise that you do not capture and share screenshots with this
advanced sample data.
For more information, see Creating New Companies in Business Central in the business functionality content.

See also
Managing Environments in the Administration Center
Preparing Demonstration Environments
Preparing Test Environments
Steps to set up a sandbox environment and Visual Studio Code
Get started with the Container Sandbox Development Environment
Prepare Demonstration Environments of Dynamics
365 Business Central
2/6/2023 • 14 minutes to read • Edit Online

As a Business Central reselling partner, you might want to have an environment that you can show prospects as
part of pre-sales demonstrations. Depending on your requirements, you have several different options that are
described in this article.
Learn more about Business Central trials and subscriptions here.

Microsoft 365 demo plus Business Central


For repeatable demos that showcase Business Central together with Microsoft apps and services in an
independent Azure organization (tenant) that you fully control, get a Microsoft 365 demo account at
https://aka.ms/CDX. You have access to the Customer Digital Experiences site if you are enrolled with the
Microsoft Partner Center.
Such Microsoft demo accounts give you environments that you can use for demos and training without the risk
of introducing changes to an existing production environment, for example. For more information about demo
accounts in general, see Offer your customers trials of Microsoft products in the Partner Center documentation.
To get a demo environment based on Microsoft 365 content packs
1. Log in to aka.ms/cdx using your partner account.
2. Choose the My Environments tab, and then, under My tenants , choose the Create Tenant button.
3. As the type, choose Quick Tenant .
4. As the period, choose either a quarter or a full year.
Your account in CDX has access to a limited quota of tenants that can last three months or a full year. For
more information, see the CDX FAQ.
5. As the location, choose the region that is closest to your location.
This setting determines the location in which the tenant is deployed, but you will be able to add Business
Central environments to it for any country/region afterwards.
6. Choose one of the available content packs and then choose the Create Tenant button.
You can choose the Dynamics 365 Business Central content pack if the location you specified is North
America, Asia/Pacific, or Europe, Middle East, Africa. This content pack includes demonstration users and
Microsoft 365 licenses.
You can also choose any of the other content packs that might better match your prospects' industry or
interests, such as the following content packs:
Microsoft 365 Business Premium Demo Content
Microsoft Teams for Consumer Goods
Dynamics 365 Customer Engagement
These content packs give you a dedicated demonstration organization in Azure that includes multiple
demo users with Microsoft 365 licenses.
NOTE
When demand for a specific content pack is high, the Create Tenant button is disabled, and you must choose a
different content pack.

Next, you sign up for a Business Central trial.


7. In a dedicated browser window, go to the https://dynamics.microsoft.com/business-central/ page, choose
the Get star ted button, and then choose the Sign up now button.
Use the new administrator account that you got as part of your demo account, typically called something
like admin@CRMbc123456.onmicrosoft.com , or admin@contoso.onmicrosoft.com .

TIP
We recommend that you use profiles in the Microsoft Edge browser rather than InPrivate or Incognito browser
mode. For more information, see Microsoft Edge documentation.

By now, you have a dedicated demonstration organization in Azure that includes multiple demo users with
Microsoft 365 licenses, and a Business Central environment.
The initial Business Central demo environment comes with two companies:
The CRONUS demonstration company
An empty company with the nameMy Company, but it might have a different display name for demo
purposes
You can keep using the demonstration company until the tenant expires, if you use it a couple of times per week.
However, if you start the trial experience or switch to the empty My Company, that experience will expire after
30 days. If the trial expires, you canextend the trial, create a new environment, or return to the CRONUS
demonstration company. For more information, see Dynamics 365 Business Central Trials and Subscriptions in
the business functionality content for Business Central.
You can now enable the Premium user experience in the new company's Company Information page,
populate the company with any data that is required for their evaluation scenarios, and present the environment
to the prospect.

IMPORTANT
Environments that are based on Microsoft 365 demo accounts are intended for demonstration and training purposes. If a
prospect uses such an environment to help run their business, then they risk losing their company data when the demo
environment or the Microsoft 365 demo account expires. If a prospect wants to use Business Central to help run their
business, they should sign up for a trial using their own email account. For more information, see Dynamics 365 Business
Central Trials and Subscriptions in the business functionality content for Business Central.

For example, if you sign up for a trial with a Microsoft 365 demo account, you can keep that environment for up
to a year. However, if you switch to the actual trial experience in Business Central, that experience will expire after
30 days. At that point, you can extend the trial, or you can return to the CRONUS demonstration experience,
which will still be available until your Microsoft 365 demo account expires.
Customize the demo environment
Since 2022 release wave 1, you can add the Contoso Coffee Demo Data app to your demo company to
showcase advanced supply chain functionality. Learn more here. 2022 release wave 2 adds connectivity apps
that you can learn more about here.
Because you are logged in as the global administrator of the demonstration tenant, you can access the Microsoft
365 administration center. The following list illustrates the types of work that your demo account can do:
Subscribe to additional apps and services that may be relevant to your demos
Configure apps and services by accessing their administration centers
Modify or add user accounts, and assign licenses
Set up the organizational profile to reflect your prospect's business and brand
Your administrator account also gives you access to the Business Central administration center, where you can
make further customizations, such as the following:
Create additional environments within the available quota, depending on your needs.
For example, you can create a Business Central environment for a specific country/region, or create a
dedicated sandbox that you then apply your solution to, such as by deploying your app straight from
Visual Studio Code. For more information, seeManaging Environments.
Specify the update window and date for your environments, so that planned updates will not interfere
with your demos.
Add your own email address to the list of notification recipients, so that you will be informed of upgrades
to your Business Central environments or any issues that may impact your planned demos.
Try out new functionality in preview environments that are available about two months before a major
update. For more information, seePrepare for major updates with preview environments.
With your administrator account, you can install apps from AppSource, and you can set up integrations between
Business Central and other services. For example, you can add the Business Central app for Microsoft Teams,
and you can run theSet up your Business Inbox in Outlook assisted setup guide on behalf of the
organization as described in the Use Business Central as your Business Inbox in Outlook article. You can also add
Dynamics 365 Customer Service,Dynamics 365 Sales,Power Automate,Power Apps, and many more.
Some content packs provide additional demonstration data for non-administrator accounts, such as example
channels and conversations in Microsoft Teams that can reduce the time needed to customize the experience for
a demo. You can log in with the demo user account, often called meganb@M365B123456.onmicrosoft.com , or
something similar, for the non-administrator experience.
Use profiles in Microsoft Edge
If you demo in the new Microsoft Edge browser, you can easily switch between different browser profiles. That
way, you do not have to use private mode for browsing, and you can let Microsoft Edge save passwords and
sites to any of your browser profiles, including a Microsoft 365 demo account. Business Central also performs
well in the Microsoft Edge for even better demos. You can also switch the page layout to Focused to minimize
demo distraction. For more information, see Microsoft Edge documentation.

TIP
We recommend that you connect to a low-latency network for a faster response time during demos, and that you always
plug in your laptop if you are about to demo anything. Performance impact may vary depending on your device and
choice of browser, but being plugged in generally helps overall snappiness.

Pre -sales performance evaluation


If you want to provide a prospect with an online environment where you want to demonstrate the performance
and reliability of Business Central online in addition to demonstrating functionality, you must take a few extra
steps.
To demonstrate the functionality of the default version of Business Central, without focusing on performance,
you can quite simply use your own trial experience based on a Microsoft 365 demo account. We recommend
that you show the full functionality of the default version by switching the tenant to the 30 day trial and the
associated My Company. You can then enable the Premium user experience in the new My Company's
Company Information page, populate the new company with the data required for their evaluation scenarios,
and present the environment to the prospect.
To demonstrate the functionality of the service, with a focus on performance, you can take the same step as
outlined above, but then also sign up the prospect for the Business Central Premium Trial offer that is available
through your CSP access in the Partner Center, wait 24 hours, and then run your performance evaluation. For
more information, see Preparing Test Environments of Dynamics 365 Business Central.
That 30 day trial is as close to an actual production environment performance as you can get. You only have
those 29 days to run your tests and convince the prospect, of course, but provided that you have prepared
everything in advance, it should give you time enough.
If the prospect is convinced and decides to buy Business Central, you can then either let them keep the
environment that they are currently using, or create a new production environment for them. If the tenant is
yours rather than the prospect's, then a new tenant will be provided to them.
For more information about performance and Business Central, see Performance Overview.

Add a Business Central trial to your prospect's organization


Any organization in the supported markets can sign up for a free trial from the
https://dynamics.microsoft.com/business-central/ page. To learn how to sign up, see the Sign up for a free
Dynamics 365 Business Central trial article.

NOTE
To explore the full capabilities in Business Central, change the user experience to Premium in the Company Information
page. For more information, see Change Which Features are Displayed in the business functionality content.

This type of environment can be useful if you want to demonstrate the general user interface, for example, or
talk about how they can add capabilities with apps from AppSource.

IMPORTANT
Specifically for businesses who want to convert a 30-day trial company into their actual production company, the first
user who signs into Business Central after the license was applied to their tenant must be a user with this license
assigned. This way, the 30-day trial ends, and any trial-related notifications disappear so that users can use Business
Central to do work.
If an administrator is the first person to sign in after the license was applied to the tenant and to users, then the trial will
continue until it expires.

If a prospect has signed up for a free trial, and they use Business Central to help run their business, then they
must decide whether to subscribe within the first 60 days. If they extend their trial once, and they are still not
sure, they must contact a partner.
However, in many cases, you will probably prefer to show prospects more tailored experiences with your own
trial as described in the Microsoft 365 demo plus Business Central section.
NOTE
If a Business Central viral trial is left unused for 45 days, Microsoft considers the trial as expired, and the Business Central
is deleted.
If the trial is converted to a paid subscription before the trial expires, the countdown to 45 days of non-usage does not
apply.

Connectivity apps
Starting in 2022 release wave 2, Business Central online environments can list one or more apps on the
Connectivity Apps and Banking Apps pages. We recommend that the admin opens the Connectivity Apps
page from the Extension Management page and allows the underlying extension to connect to its external
service either once or always. Business Central then connects to AppSource to generate a short list of apps that
have been approved for that country or region. These particular apps can connect to external services, such as
online banking.
If you are an ISV and want your banking app to show up in the Connectivity Apps page, reach out to us at
Microsoft. We're testing the suggested apps according to business and functional requirements. The list relies on
AppSource and is intended to show the best apps in that business's country or region for core connectivity
scenarios. Learn more at Requirements for Connectivity Apps.

Use Contoso Coffee demo data for advanced manufacturing


The Contoso Coffee Demo Data app for Business Central includes demo data that you can add to a trial
company or a sandbox environment to showcase or learn advanced manufacturing capabilities. For more
information, see Introduction to Contoso Coffee Demo Data and Scenarios for Contoso Coffee Demo Data in the
business functionality content.

Add Dynamics 365 Sales Professional


Once you have a Microsoft 365 demo account as described in the To get a demo environment based on
Microsoft 365 content packs section, you can use the admin account to also sign up for a trial of Dynamics 365
Sales Professional so that you can demo the integration of the Sales app and Business Central.

TIP
Integration between Business Central and Sales happens through Dataverse. For more information, see Integrating with
Dynamics 365 Sales in the business functionality content.

To add Dynamics 365 Sales Professional to your Microsoft 365 demo account
1. In a dedicated browser window, sign in as the admin account for the Microsoft demo account that you
created in the To get a demo environment based on Microsoft 365 content packs section. For more
information, see the Use profiles in Microsoft Edge section.
2. Go to the Microsoft Dynamics 365 Sales Professional marketing page, and choose the Tr y free action,
and then follow the guidance in the steps to add the Sales trial to your account.
Once the trial is available, proceed to the next step.
3. In another browser tab, sign into Business Central at https://businesscentral.dynamics.com/?
redirectedFromSignup=1.
4. Choose the icon, enter Dataverse Connection Setup , and then choose the related link.
5. Follow the steps in the wizard to connect to your Sales trial.
To finish setting up the connection, you must run the Sales-specific assisted setup.
6. Choose the icon, enter Dynamics 365 Connection Setup , and then choose the related link.
7. Follow the steps in the wizard to connect to your Sales trial.

Richer demos with the Customer Engagement content pack


In certain scenarios, you want to demo richer integration capabilities than the Sales Professional app offers. In
those cases, you follow the same steps to get a Microsoft 365 as is described in the To get a demo environment
based on Microsoft 365 content packs section. But you choose the more advanced Dynamics 365 Customer
Engagement content pack so that you can demo integration with Power Apps, Power Automate, and the
Dynamics 365 Sales Enterprise, for example.
To get richer demo environments with Dataverse and the Customer Engagement content pack
1. Follow the steps in the To get a demo environment based on Microsoft 365 content packs section. But at
step 6, choose the more advanced Dynamics 365 Customer Engagement content pack.
2. Complete step 7 in the procedure where you sign into Business Central with the new Microsoft 365
tenant's admin credentials.
Next, you move to the Power Platform to prepare the demo environment.
3. Sign into the Power Platform Admin Center with the same admin credentials.
4. In the list of environments, choose the trial environment, and then choose the Conver t to production
action.

NOTE
The trial environment will have the Type field set to Trial (29 days). Do not convert the default environment.

After a few minutes, the trial environment is converted to a production environment, and the Type field
changes to Production.
5. Choose the converted environment again, and then choose the Conver t to sandbox action.
We recommend that you convert the environment to a sandbox environment for demo purposes. In the
sandbox environment, you can:
Reset the environment without any Dynamics 365 apps, which effectively gives you an empty Dataverse
database to connect to using the Set up Dataverse connection assisted setup if you want to integrate
Business Central just to Dataverse.
For more information, see Reset environment in the Power Platform docs, and Integrating with Microsoft
Dataverse in the business functionality content for Business Central.
Reset the environment with specific Dynamics 365 apps with or without sample data to demo to various
audiences. For more information, see Reset environment.
For example, when you reset the sandbox environment, you can choose to deploy Sales enterprise and
demo integration between Business Central and the full capabilities of Dynamics 365 Sales. For more
information, see Integrating with Dynamics 365 Sales in the business functionality content.

Demo in a sandbox environment


You can set up tailored demo environments in a sandbox environment if you already have a Business Central
tenant. For example, to show two different implementations of a capability, or to illustrate an integration point.

NOTE
Sandboxes are limited in functionality, including performance. For more information, see Sandbox environments.

Starting in February 2022, partners can request dedicated licenses to set up additional sandbox environments.
For more information, see Partner sandboxes.

See also
Preparing Test Environments of Dynamics 365 Business Central
Trials and Subscriptions
The Business Central Administration Center
Managing Environments
Administration of Business Central Online
Data and access when a trial or subscription ends
Deployment of Dynamics 365 Business Central
Offer your customers trials of Microsoft products
Preparing Test Environments of Dynamics 365
Business Central
2/6/2023 • 2 minutes to read • Edit Online

As a Business Central reselling partner, you might want to have an environment that you can use for testing or
pre-sales demonstrations. You can create such environments based on free 30 day trials, or you can set up a
dedicated environment if you have a Business Central subscription yourself.

Test environments based on a 30 day trial


This type of environment can be useful if you want to run benchmark tests, for example. The following
procedure requires CSP access in Partner Center. If you do not have CSP access, you can work with your CSP
distributor to do this for you. For more information, see the Partner Center documentation.
To create a test environment based on a 30 day trial
1. In Partner Center, create a new test customer with any test domain, such as contoso.onmicrosoft.com. For
more information, see Add a new customer in the Partner Center docs.
a. Fill in the fields as described in the following list:

F IEL D VA L UE

Countr y <Your country>

Subscription Dynamics 365 Business Central Premium Trial

This will give you 25 Premium licenses for 30 days


for free

b. Make a note of the Admin credentials that are shown on the last page of the customer creation
wizard. You will need these credentials later.
2. In Partner Center, once the test customer has been created, create a new test user. For more information,
see Create user accounts for a customer in the Partner Center documentation.
3. Assign that user 1 Premium license.

NOTE
It may take up to 10 minutes for the available licenses to show up on the Users page.

Also, make a note of the user credentials shown on the last page of the user creation wizard. You will use
this information in step 55
4. In the Ser vice Management section, choose the Dynamics 365 Business Central link.
This opens the Business Central administration center at the equivalent of the following URL:
https://businesscentral.dynamics.com/contoso.onmicrosoft.com/admin

In the Business Central administration center, you can create new production and sandbox environments
for the test customer.
TIP
Always include the domain or the Azure Active Directory ID of the customer in the URL when you login as a
delegated admin. This way, you always know exactly which customer you are trying to access.

5. Access Business Central as the local user that you created in step 2.
a. Open another browser window in InPrivate or Incognito mode. This way, you can make sure that
you are not logging in with your own credentials.

TIP
We recommend that you use profiles in the Microsoft Edge browser instead. For more information, see
Microsoft Edge documentation.

b. Go to https://businesscentral.dynamics.com/, and then, when you are asked to sign in, use the
credentials of the user you created in step 2.
The Business Central environment is created automatically when you use the environment URL to login the first
time.

Prepare for major updates with preview environments


About two months before a major update, you can try out new functionality in preview environments. For more
information, see Prepare for major updates with preview environments.

See also
The Business Central Administration Center
Managing Environments
Preparing Demonstration Environments
Prepare for major updates with preview environments
Administration of Business Central Online
Deployment of Dynamics 365 Business Central
Get Started as a Reseller of Business Central Online
Offer your customers trials of Microsoft products
Prepare for major updates with preview
environments
2/6/2023 • 4 minutes to read • Edit Online

About one month before a major update, you can try out new functionality in preview environments. Preview
environments are Business Central online sandbox environments that you create on a preview version of the
application. When you create the new sandbox environment, choose the preview version marked as (Preview)
from the version list. This way, you get a new sandbox environment with a preview version of the application.
Use Microsoft Collaborate to submit your feedback or to report any potential issues that you discover in the
preview. For more information about getting access to Collaborate, see Step 4 in the readiness section for
developers.

NOTE
Previews roll out gradually across the world, so if the option is not showing up for you today, please try again tomorrow.

The newly created preview sandbox environment contains demonstration company data. Trying the preview on
a copy of your current production data is not yet supported; nor is testing the upgrade from your current
version to the preview. However, you can use the newly created sandbox environment for exploring and learning
the new product capabilities. You can also use the preview environment to validate that any per-tenant
extensions are still working as expected.
If you run your tests on a preview environment one month before the announced major release of Business
Central, it is more likely that the coming updates of your production environments will go smoother. This way,
you, your customers, and your code are better prepared for the official release.
We expect to update the preview version only if we discover critical issues before the major update is generally
available for production environments. Apart from these potential fixes, we do not expect any further changes to
the product between the preview and the official release. You can start your testing and learning activities
immediately, without waiting for the official release.

NOTE
You will be able to test the update on a copy of your production data in a sandbox environment when we release the new
update in production in April or October, respectively. When the official release becomes available, you can continue your
tests on that version. You will no longer be able to create new preview sandboxes.

IMPORTANT
The preview version as well as all sandbox environments that are based on it will be removed 30 days after the official
release becomes available.

The following figure illustrates the suggested steps for getting a preview of a major update with example dates
for the two release waves in any given calendar year.
For more information, see Major Updates and Minor Updates for Business Central Online.

Practice and test


Once you have the preview, start using it:
1. Review the new functionality. Try it out, and begin training employees on the new features that are
coming.
2. Validate your extensions.
Upload and install your extensions into the sandbox environments created on the preview version and
run through the functionality. Verify that the customization continues to work and is compatible with the
new version.
In rare cases, if you discover any changes required for your per-tenant extension to become compatible
with the next release, apply the changes to your app, test it again on a sandbox environment running on a
preview version. Then, if tests complete successfully, upload the app into your production environment,
setting the Deploy to field to Next major version. This way, the compatible version of your app will be
used when you schedule the upgrade of your production environment to the new major update once it
becomes available.
3. Test the quality. If you run into issues related to the preview, please provide feedback on Collaborate.
Finally, as always, if you have ideas for features you would like to see in future releases of Business Central, let
us know at https://aka.ms/bcideas.

Provide feedback on the preview


We need your feedback on the preview! Let us know about your experiences with the new version. You can
provide feedback on Microsoft Collaborate:
1. Browse to aka.ms/collaborate
2. If you have not registered before, complete the registration form to access Collaborate
3. Choose Engagements , and then choose the Join action
4. Under the Ready! for Dynamics 365 Business Central program, find the latest preview version in the
list of available engagements, and then choose the Join action
Once you have joined the preview engagement, you can submit your feedback by filling in the form. You must
specify if you are reporting a technical issue, a translation issue, or a documentation issue. The default severity is
set to 3, which is the normal severity for most defects and means that the system is not crashing and users are
not blocked from doing their work, but you can change that. When we have triaged your issue, you can see
changes in Collaborate.
TIP
If you get stuck trying to join Collaborate, please contact dyn365bep@microsoft.com with as many details about the
error that you got and other circumstances.

See also
Major Updates of Business Central Online
Managing Major and Minor Updates of Business Central Online
Working with Administration Tools
The Business Central Administration Center
Managing Environments
Managing Tenant Notifications
Step 4: Getting access to preview bits
The Business Central Administration Center
2/6/2023 • 3 minutes to read • Edit Online

The Business Central administration center provides a portal for administrators to do administrative tasks for a
Business Central tenant. Here, administrators can:
view and work with production and sandbox environments for the tenant.
set up upgrade notifications.
view telemetry for events on the tenant.

Access to the administration center


The following users are authorized to access the Business Central administration center:
Internal tenant administrators
Admin agent
Helpdesk agent
Internal administrators are users who are assigned the Global admin role or the Dynamics 365 Admin role
in the Microsoft 365 admin center. These users are typically system administrators, IT professionals, or super
users at the customer's company. For more information, see About admin roles in the Microsoft 365 admin
content.
The admin agent and helpdesk agent roles are assigned through the Microsoft Partner Center for the partner
that is associated with the tenant. These roles can access the Business Central tenant as delegated
administrators. For more information, see Administration of Business Central Online.

Internal administrators
As the internal administrator, you can choose the link in the Settings menu when you're signed in to Business
Central.
Alternatively, you can access the administration center from the URL, use the following pattern but replace
[TENANT_ID] with the tenant ID of your Business Central:
https://businesscentral.dynamics.com/[TENANT_ID]/admin

TIP
The tenant ID is shown in the Help and Suppor t page in your Business Central.
In the administration center, you can create and monitor environments. This is also where you manage the
people who must be notified of administrative events for your tenant.
Your partner can help you set up telemetry for production environments, including integration with Application
Insights in Azure.
Cleaning up settings
If your organization decides to switch to another partner, you must make sure that some settings that your
current partner made in your Business Central administration center are removed. This includes the following
settings:
Support contact details
1. In the Business Central administration center, choose the relevant environment, and then, in the
Suppor t menu, choose Manage Suppor t Contact .
2. Verify that the values in the Name , Email address , and the Website fields are still relevant; if not,
then delete or modify the values.
Notification recipients
1. In the Business Central administration center, on the left side, choose Notification recipients
2. Verify that the list of email addresses are still relevant; if not, then delete or modify the values.
Application Insights key (if this was set up by the partner)
1. In the Business Central administration center, choose the relevant environment, and then, in the top
menu, choose Application Insights Key .
2. Remove the value of the Instrumentation Key
Authorized Azure Active Directory Apps (if this was set up by the partner)
1. In the Business Central administration center, navigate to 'Authorized AAD Apps' and remove any apps
authorized by the partner.
2. Revoke consent granted to the AAD App belonging to the partner from your AAD Tenant. For more
information, see here.
3. Removed apps may have additional permissions assigned to execute certain administration
operations, such as the D365 BACKUP/RESTORE permission. Any apps set up with permissions in
Business Central can be disabled from the Azure Active Director y Applications page. For more
information, Assign Permissions to Users and Groups.
When you establish a relationship with a new partner, they will fill in these fields again.

Partner access to the administration center


As a partner, you can access the administration center from the Partner Dashboard in the Microsoft Partner
Center:
1. Log into the Partner Dashboard.
2. Select the Customers link in the navigation pane.
3. Select the customer tenant that you want to do administrative tasks for.
4. Select Ser vice Management .
5. Under the Administer Ser vices heading, select Dynamics 365 Business Central.
You can also get to the administration center by using the URL of a tenant, as described in the previous section.
In the Business Central administration center, you can specify support information, create and remove
environments, and submit support request for your customer.
From the Business Central administration center, you can access your customer's Business Central for
troubleshooting, for example.

NOTE
As the partner, there are certain tasks that you cannot do in your customers' Business Central. For more information, see
Acting as a delegated administrator.

See also
Production and Sandbox Environments
Managing Environments
Tenant Notifications
Environment Telemetry
Administration Center API
Managing Technical Support
Business Central Data Security
Introduction to automation APIs
Microsoft Partner Dashboard
Add a new customer in the Partner Center
Assign licenses to users in the Partner Center
Create new subscriptions in the Partner Center
Cloud Solution Provider program - selling in-demand cloud solutions
Managing Production and Sandbox Environments in
the Admin Center
2/6/2023 • 11 minutes to read • Edit Online

The Environments tab of the Business Central administration center provides you with an overview of the
Business Central production and sandbox environments for the tenant, and you can manage updates for each
environment.

Viewing details for an environment


In the environments list, you can view more details by choosing the link in the Name column.

Types of environments
You can create environments of different types. Choose the type of environment based on what you need it for.
For more information, see Production and Sandbox Environments.
Production environments
Production environments are meant to be precisely that: Environments that a business can run their daily
business in Business Central in, deployed on performance tiers in Azure with a guaranteed high level of
availability and support.
Production environments are backed up automatically and frequently to help protect business data. For more
information, see How often are production databases backed up?.
You can create additional production environments for training or performance testing, for example. However,
for training purposes, in many cases organizations will prefer to create a sandbox environment with production
data. You can also create additional production environments to support offices in different countries.
A production environment can have a state of suspended if the subscription has been suspended, or if the
environment has not been accessed for a long time. In those cases, you can only publish extensions to such an
environment if it only has evaluation companies. If the suspended environment has been used for actual
production so that it contains companies that are not evaluation companies, then you cannot publish extensions
to it.

NOTE
The Premium and Essential subscription types give each Business Central customer one production environment and
three sandbox environment free of extra charge. If the customer requires more production environments, they can buy
additional environments through their CSP partner. Each additional production environment comes with three additional
sandbox environments and 4 GB additional, tenant-wide database capacity. In addition, starting in 2023 release wave 2,
there's a limit on how many companies you can have on a single tenant (see Operational limits).

Administrators can create the additional environments in the Business Central administration center. The
environments can be created and used in any country or region where Business Central is available, including
the countries or regions where the customer's existing environments are running. The environments quota is
applied when you try to create a new environment, or copy an existing environment, in the Business Central
administration center.
Sandbox environments
Sandbox environments are meant to be precisely that: Environments that you can play around with, use as a
testbed for development, and delete at will. You can deploy apps straight from Visual Studio Code to a sandbox
environment, and you can attach a debugging session to a sandbox.

IMPORTANT
Apps that are published to a sandbox from the development environment or created using Designer are published within
the scope of the service node that hosts the environment. When the sandbox is upgraded, these apps are removed
because the environment is moved to another node that is running the new version. However, the data of the app is not
removed, so you only have to re-publish and install the app to make it available.
Apps that are uploaded to the environments of both types (production and sandbox) using the Upload Extension
action from the Extension Management page are published within a global scope. When the environment is upgraded
or moved, these apps are downloaded to the service node and installed, which means that they will not disappear.

You can also safely use sandboxes for training, such as for following a learning path from Microsoft Learn,
because it's a safe environment to experiment with. If anything goes wrong, you just delete the sandbox and
start over.

IMPORTANT
The automatic backup that applies to production environments does not apply to sandbox environments. If you want to
export data from a sandbox environment, you can use Excel or RapidStart, but you cannot request a database export.

You can create a sandbox environment that includes data from your production environment for debugging
purposes, for example. But if you want to run performance tests, or similar benchmarking, the sandbox is not
reliable enough for that purpose. This is because sandboxes run in a different performance tier on Azure than
production environments. Instead, create a dedicated environment based on the Production environment type -
this gives you the exact experience and performance that users will experience in the actual production
environment.
Sandbox environments are handy for certain types of development scenarios because the debugging endpoint
is open by default. This means that you can attach Visual Studio Code to a running system and debug through
running code. It also allows you to publish directly to the environment from Code.
If your organization has more than one sandbox environment, you can switch between environments by
opening the App Launcher, choosing the Dynamics 365 tile, then choose the Business Central Sandbox tile. The
sandbox environment picker shows the available sandboxes, so choose the one that you want to switch to.

NOTE
The Premium and Essential subscription types give each Business Central customer one production environment and
three sandbox environment free of extra charge. If the customer requires more production environments, they can buy
additional environments through their CSP partner. Each additional production environment comes with three additional
sandbox environments and 4 GB additional, tenant-wide database capacity. In addition, starting in 2023 release wave 2,
there's a limit on how many companies you can have on a single tenant (see Operational limits).

Administrators can create the additional environments in the Business Central administration center. The
environments can be created and used in any country or region where Business Central is available, including
the countries or regions where the customer's existing environments are running. The environments quota is
applied when you try to create a new environment, or copy an existing environment, in the Business Central
administration center.
Pre -sales performance evaluation
If you want to provide a prospect with an online environment where you want to demonstrate the performance
and reliability of Business Central online in addition to demonstrating functionality, you must take a few extra
steps.
To demonstrate the functionality of the default version of Business Central, without focusing on performance,
you can quite simply use your own trial experience based on a Microsoft 365 demo account. We recommend
that you show the full functionality of the default version by switching the tenant to the 30 day trial and the
associated My Company. You can then enable the Premium user experience in the new My Company's
Company Information page, populate the new company with the data required for their evaluation scenarios,
and present the environment to the prospect.
To demonstrate the functionality of the service, with a focus on performance, you can take the same step as
outlined above, but then also sign up the prospect for the Business Central Premium Trial offer that is available
through your CSP access in the Partner Center, wait 24 hours, and then run your performance evaluation. For
more information, see Preparing Test Environments of Dynamics 365 Business Central.
That 30 day trial is as close to an actual production environment performance as you can get. You only have
those 29 days to run your tests and convince the prospect, of course, but provided that you have prepared
everything in advance, it should give you time enough.
If the prospect is convinced and decides to buy Business Central, you can then either let them keep the
environment that they are currently using, or create a new production environment for them. If the tenant is
yours rather than the prospect's, then a new tenant will be provided to them.
For more information about performance and Business Central, see Performance Overview.

Create a new environment


The Business Central administration center provides an easy method for creating environments for the tenant.
For example, you've been using a production environment for training purposes, and you've decided to start
using Business Central to run the business. You can, in this case, delete the original production environment and
then create a new production environment.

NOTE
The Premium and Essential subscription types give each Business Central customer one production environment and
three sandbox environment free of extra charge. If the customer requires more production environments, they can buy
additional environments through their CSP partner. Each additional production environment comes with three additional
sandbox environments and 4 GB additional, tenant-wide database capacity. In addition, starting in 2023 release wave 2,
there's a limit on how many companies you can have on a single tenant (see Operational limits).

Administrators can create the additional environments in the Business Central administration center. The
environments can be created and used in any country or region where Business Central is available, including
the countries or regions where the customer's existing environments are running. The environments quota is
applied when you try to create a new environment, or copy an existing environment, in the Business Central
administration center.
You can create new environments that are either production environments or sandboxes. You can also copy an
existing environment. For more information, see Copy a Production or Sandbox Environment.
To create a new environment that isn't a copy of an existing environment
1. On the Environments tab of the Business Central administration center, choose the New action on the
action ribbon.
2. In the Create Environment pane, Specify a name for the new environment.
3. In the Environment Type list, choose Production or Sandbox .
4. In the Application family field, specify the type of solution that this environment is based on if it isn't
Business Central.
5. In the Countr y list, select the country for the environment. The specified country determines the
localization for the environment and the Azure region in which the environment is created and stored.

NOTE
The new environment will be created with a default update window that guarantees future updates won't run
between 8:00 PM and 6:00 AM local time for the environment country. This update window can be changed after
the environment has been created. For more information, see Managing Updates in the Business Central Admin
Center.

6. In the Version list, specify the relevant application version for the new environment if more than one
version is available.
7. Choose the Create action.

NOTE
The new environment won't be accessible until the State shows Active.

New production environments are based on the latest production version of Business Central. New sandboxes
are based on the specified version.
IMPORTANT
Make sure that you understand the limitations of a sandbox before you create a new sandbox environment. For more
information, see the Sandbox environments section.

To delete an environment, choose the environment on the Environments tab of the Business Central
administration center, and then choose Delete on the action ribbon.
Selecting a version for a new sandbox environment
If you create a sandbox that isn't a copy of an existing environment, you must specify an application version for
the new environment. The version list will show the latest production version, which is the version used for new
production environments.
The version list may also have one or more preview versions. Preview versions are early release candidates of
upcoming releases of Business Central that are made available specifically for sandbox environments. This list
gives you access to review new functionality, validate extension compatibility, and other general testing of the
upcoming release.
When you create a sandbox environment on a preview version, the environment will automatically be updated
to new preview versions when they become available. However, the environment won't be updated to the
production version. Once a sandbox environment is on a preview version, it must stay on a preview version until
it's deleted. The environment can also be deleted if an update between preview versions fails. We recommend
that preview versions are used only for temporary testing of an upcoming release.

Delete an environment
You can delete environments in the admin center, such as when a sandbox environment isn't longer needed.

IMPORTANT
Make sure no user is using the environment before you delete it.
Also, be very careful before you choose the Delete action for the environment. The action is irreversible.

Log of administrative operations


The Operations section of Business Central administration center provides a log of operations that internal
administrators and delegated administrators from the partner have made in the Business Central administration
center or through the admin center API. Use this log to see which operations were created and when. You can
also access detailed error messages in this log, should any operation fail.
Operations
Currently, the log includes the following operations:

EXT EN SIO N
TYPE DESC RIP T IO N A DM IN C EN T ER API M A N A GEM EN T PA GE

Copy environment An environment was See... See...


created from a copy
of another
environment.

Create environment A new environment See... See...


was created
EXT EN SIO N
TYPE DESC RIP T IO N A DM IN C EN T ER API M A N A GEM EN T PA GE

Delete environment An environment was See... See...


deleted.

Modify environment One of the following See update See environment


operations was done management... settings...
on an environment:
Set update See telemetry...
window
Set See manage access...
Application
Insights
connection
string
Set security
group
Clear security
group
Reschedule
update
Set access
with
Microsoft 365
licenses.

Move environment An environment was See...


moved to another
Azure Active
Directory
organization.

Rename environment Environment was See... See...


renamed.

Restart environment Environment was See...


restarted

Update environment An environment is See... See...


updated to a newer
version.

Environment app A hotfix was applied See...


hotfix to the app by using
the App
Management API.

Environment app App was installed by See... See...


install using the tenant's
Extension
Management page
or the API install
endpoint.
EXT EN SIO N
TYPE DESC RIP T IO N A DM IN C EN T ER API M A N A GEM EN T PA GE

Environment app App was uninstalled See... See...


uninstall by using the tenant's
Extension
Management page
or the API uninstall
endpoint.

Environment app App was updated See... See...


update either by the Admin
Center or API update
endpoint.

Retention period
The operations are kept for 180 days, after which they're deleted.

See also
Managing Tenant Notifications
Managing Apps
Updating Environments
Managing Sessions
Copy a Production or Sandbox Environment
Rename Environments
Restoring an Environment
Move an Environment to another Azure Active Directory organization
Introduction to automation APIs The Business Central Administration Center
Manage Access to Environments
2/6/2023 • 3 minutes to read • Edit Online

This article describes admin center features that you use for controlling user access to environments. In addition
to what you do in the admin center, these features typically require configuration and set up in either Business
Central or another product or service.

Manage access using Azure Active Directory groups


To manage access at the environment level, you can assign an Azure Active Directory (Azure AD) group to the
environment. By assigning an Azure AD group to an environment, only direct and indirect members of the
group are granted access to the environment. Indirect members are users in another group, which itself is a
member of the group assigned to the environment. Although all licensed users in Azure AD will be added to the
environment when it's synchronized with Microsoft 365, only group members can sign in.
From the Environments page, you'll see the currently assigned group in the Security Group column. Not set
indicates that no group has been assigned. Not available indicates that the group that was assigned is no
longer available in the Azure AD.

NOTE
The restrictions imposed by a security group don't apply to administrators. Local and delegated admins can freely sign in
to all environments, regardless of the assigned group.

Assign, change, or remove a group


Before you can assign an Azure AD group to an environment, the group must be created in your Azure AD
tenant. For more information, see Create a basic group and add members using Azure Active Directory in the
Azure documentation.
1. Select Environments , then select the environment on which you want to assign, change, or remove the
group.
2. On the Environment Details page, the currently assigned group is shown under Security Group .
To assign a group, select (Define) .
To change or remove the currently assigned group, select Modify .
3. The Edit Security Group pane shows the current security group, if any, followed by all the available
groups in Azure AD.
To assign or change a group, search for and select the group from the list.
To remove a group, select under Current Security Group .

NOTE
If there are more than 10,000 groups in Azure AD, they can't all be retrieved and displayed in the admin center.
Instead, you'll see the message You have too many groups to display them all. In this case, you'll have to
enter the object ID of the group that you want to assign. You get the object ID from the Azure portal.

4. Select Save when done.


NOTE
If you change or remove a group, it can take a while before the changes to take effect or access is revoked from users.

Manage access with Microsoft 365 licenses


To help Business Central users easily share and collaborate on business data with their coworkers, you can
enable access with Microsoft 365 licenses. When enabled, users within the same organization who have an
applicable Microsoft 365 license will be able to read (but not write) Business Central data that is shared with
them in Microsoft Team—without needing a Business Central license.

NOTE
This setting is only available for environments of platform version 21.1 or later.

Enabling access to an environment is one of multiple steps required to configure this capability. We recommend
that you complete all other setup steps before enabling access for an environment from the Business Central
admin center. Learn more at Set Up Access with Microsoft 365 licenses.
To turn access on or off, complete the following steps:
1. SelectEnvironments , then select the environment on which you want to change license access.
2. On the environment details page, select Modify for the Access with Microsoft 365 licenses setting.
3. In the Microsoft 365 licenses pane, turn the switch on or off.
4. Select Save and accept the confirmation dialog. The change takes effect immediately.

See also
Managing Environments
Managing Apps
2/6/2023 • 5 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1

A Business Central environment is built as a collection of apps. These apps include Microsoft apps and third-
party apps, for example, apps from AppSource. The apps work together to provide customers with a broad set
of features to address their various business, market, and industry needs.
Updates are frequently made available for these apps by Microsoft, partners, and ISVs. App updates add new
features and fix known problems. To keep your environment up to date and running smoothly, you should check
for and install the latest updates regularly.
To help you manage app updates, the administration center includes the Manage Apps page.
Like other features in the administration center, this functionality can be used by the partner (delegated
administrator) or a local customer admin.

NOTE
In the current version, it's not possible to install new apps, either main apps or their dependencies (library apps), by using
the Manage Apps . To install the apps, continue using the Extension Management page within your Business Central
environment.

Get an overview and check for updates


Open the Manage Apps page from the environment details page. Choose Environments > select the
environment > Manage Apps .

The Manage Apps lists all the apps installed on the environment and indicates whether updates are available.
When first opened, the system will start checking for updates. Wait for this operation to complete.
IMPORTANT
When an ISV provides a new version of their AppSource app, Microsoft validates it against the latest, currently available
version of Business Central at the time. If the new app version passes validation, it's made available for the customers'
environments that are running on that version of Business Central and greater. So if you're not seeing an AppSource app
update in the list, your environment may not yet be running on the version the app was registered for.

When completed, if an update is available for an app, there are two indications:
The Latest Available Version column contains the new version number of the app.
The Available Update Action column contains one of the following actions:

A C T IO N S DESC RIP T IO N S

Action required This action means that you have to do something before
you install the update for the app. For example, you may
have to first update another app or install a new app.
Select the link and read the Requirements for App
Updates pane to see what is required. For more
information, see Resolving requirements for app updates.

Install update This action means that the app is ready to install. Select
the link to start the installation.

Install an app update - the flow


We recommend you always install and test an app update on a Sandbox environment first. Make sure the app
update won't disrupt the operational flow or cause problems for the users.
The following steps provide the general flow for updating an app.
1. If you don't have a sandbox environment, create one. For more information, see Create a new
environment.
2. Open the Sandbox environment and select Manage Apps .
3. On the Manage Apps , find the app in the list that you want to update.
4. If the Available Update Action column for the app shows the Action required link, resolve the update
requirements.
See Resolving requirements for app updates.
5. When the Available Update Action column for the app shows Install update , select this action to
install the new version of the app.

IMPORTANT
The update will be applied immediately after you accept the confirmation dialogue. The users can continue
working during update installation, but depending on the app changes coming with the update, they may receive
a message asking them to log out and login again. It is therefore recommended that you apply the updates
outside of working hours.

6. Wait for the app to be installed.


Select Refresh occasionally to check the status.
If the app installs successfully, the new version displays in the Installed version column and the
Available Update Action column is Up to date .
If the installation fails the Available Update Action column changes to Update failed . See What to
do when an update fails.
7. If the app update succeeded, sign in the Sandbox environment and test the new app version.
8. If the app update works as expected on the Sandbox, switch to the production environment, and repeat
the installation steps for the app update.

TIP
Use the environment switch box at the top of the page to quickly change to your production environment.

Resolve requirements for app updates


For apps that have dependencies on other apps, you may have to update or install the dependency apps. The
Requirements for App Updates page provide this information. The requirements are divided into two
categories: Update requirements and Install requirements .
After you resolve all requirements, the app that you want to update will be ready to install.
Update requirements
The Update requirements category lists existing dependency apps the have updates to be installed. To resolve
these requirements, do the following steps for each app:
1. Return to the Manage Apps page.
2. Find the app in the list and select Install update .
3. Wait for Available update action column to change to Up to date .
Install requirements
The Install requirements category lists dependency apps that haven't been installed yet. For example, a new
app was introduced that app update depends on.
You can't, however, install a new app from the Manage App page. Use the Extension Management page in
the client instead. Completing this step will resolve the requirement. For more information, see Installing an
Extension.

What happens when an app update is installed?


The new app version is starting to install immediately, following the confirmation dialogue. The new app version
will be published, synchronized, and updated in the background. This process usually doesn't take long, and
users won't be interrupted. However, we still recommend you to install the updates outside of working hours.

What do I do when an update fails?


When the installation of an app update fails, the Available Update Action column will display the Update
failed action. Select this action to get more information. The App Update Details pane provides some details
about update and what might have caused the failure.
Sometimes the update could fail because of a transient problem. Select Retr y to try to install the update again.
If the installation continues to fail, contact your ISV. You can find the support details of each ISV on their app
page on AppSource. Contact Microsoft support if the app publisher is Microsoft .
TIP
When reporting issues to Microsoft Support, always provide the Operation ID displayed in the error message. This will
help expedite the investigations.

See also
Working with Administration Tools
The Business Central Administration Center
Production and Sandbox Environments
Managing Environments
Updating Environments
Managing Tenant Notifications
Introduction to automation APIs
Managing Capacity
2/6/2023 • 7 minutes to read • Edit Online

To help our customers manage and plan their storage costs on an ongoing basis, the Business Central
administration center includes the Capacity page. The Capacity page provides an overview of the total
database storage usage, with details about the storage used by every environment. The page also displays the
currently used and the maximum allowed number of production and sandbox environments available for the
customer.
By default, Business Central customers can use up to 80 GB of database storage capacity across all their
environments (production and sandbox). This limit means that the sum of database capacity usage across all of
their environments must not exceed 80 GB. If a tenant exceeds this limit, Microsoft restricts administrative
actions that create additional environments. Exceeding the storage limit will not interrupt transaction processing
within the existing environments.
Some businesses have unique scenarios that may require additional storage. For those organizations that need
more space, there's an option to purchase extra database capacity.
Customers can purchase additional database capacity and environments through their reselling partner by
using the following add-ons to their existing license:
Dynamics 365 Business Central Database Capacity (1 GB)
Dynamics 365 Business Central Database Capacity (100 GB)
Dynamics 365 Business Central Database Capacity Overage (1 GB)
This lower-priced add-on is only available for the customers who purchased at least one Dynamics 365
Business Central Database Capacity (100 GB) add-on.
Dynamics 365 Business Central Additional Environment Add-on

Number of environments
Business Central administrators can create multiple sandbox and production type environments for various
purposes, like:
Creating more business branches
Moving into more countries
Expanding within their current country
Development
Testing changes
Learning new product capabilities
Every Business Central customer with Business Central Premium or Essential subscriptions can use one
production environment and three sandbox environments, at no extra charge.
Customers can also choose to purchase any number of additional production environments via their CSP
partner. Each additionally purchased production environment comes with three additional sandbox
environments.
Production and sandbox environments can be created and used in any country where Business Central service
is available, also in the country where the default Business Central environments are located. Additional
environments can be created by customers, administrators, and partners by using the Business Central
administration center.
When customer administrators create users in Microsoft 365 Admin Center and assign them Business Central
licenses, each user, by default, gets access to all Business Central environments (sandbox and production) under
the same single Business Central license, still acting within the scope of their license within each of these
environments. Administrators can limit users' access to any particular environment by changing their
permissions, or by removing users' access within that environment.
Customers with Premium or Essentials subscriptions purchased before October 1 2020
Existing customers with Business Central Premium or Essentials subscriptions purchased before October 1 2020
will keep their existing environment entitlements (three production and three sandbox environments) for one
year, until October 1 2021 or until their subscription is renewed or ended, whichever occurs last.
Access to two additional production environments during this period won't increase your overall database
storage capacity and won't enable extra sandbox environments. These benefits are only activated with the
production environments purchased by the customers separately.
Examples:
Your Business Central subscription renews before October 1 2021
You can use up to three production environments until October 1 2021. After that date, you'll only be
entitled to one production and three sandbox environments.
Your Business Central subscription renews after October 1 2021
You can use up to three production environments until the day your subscription renews. After that date,
you'll only be entitled to one production and three sandbox environments.
When your entitlement for two additional production environments expires, the additional production
environments you may have created during that period will still be fully available. You won't be automatically
charged for the extra environments. But to become compliant, you'll have to purchase additional production
environments via your CSP partner within 30 days following the expiration date. For more information, see the
Exceeding capacity quotas section.
Use the Capacity page to see how many environments of each type you have available for your organization.

Storage
Storage capacity usage of Business Central is represented by Database on the Capacity page.
By default, Business Central customers can use up to 80 GB of database storage capacity across all their
environments (production and sandbox). This limit means that the sum of database capacity usage across all of
their environments must not exceed 80 GB. If a tenant exceeds this limit, Microsoft restricts administrative
actions that create additional environments. Exceeding the storage limit will not interrupt transaction processing
within the existing environments.
Some businesses have unique scenarios that may require additional storage. For those organizations that need
more space, there's an option to purchase extra database capacity.
NOTE
The Premium and Essential subscription types give each Business Central customer one production environment and
three sandbox environment free of extra charge. If the customer requires more production environments, they can buy
additional environments through their CSP partner. Each additional production environment comes with three additional
sandbox environments and 4 GB additional, tenant-wide database capacity. In addition, starting in 2023 release wave 2,
there's a limit on how many companies you can have on a single tenant (see Operational limits).

Administrators can create the additional environments in the Business Central administration center. The
environments can be created and used in any country or region where Business Central is available, including
the countries or regions where the customer's existing environments are running. The environments quota is
applied when you try to create a new environment, or copy an existing environment, in the Business Central
administration center.
Apart from the default storage capacity, the customer is entitled to additional storage capacity based on the
number of Business Central licenses they own:

L IC EN SE T Y P E A DDIT IO N A L STO RA GE ( F O R EA C H L IC EN SE O F T H IS T Y P E)

Premium 3 GB

Essential 2 GB

Device 1 GB

Customers can purchase additional database capacity and environments through their reselling partner by
using the following add-ons to their existing license:
Dynamics 365 Business Central Database Capacity (1 GB)
Dynamics 365 Business Central Database Capacity (100 GB)
Dynamics 365 Business Central Database Capacity Overage (1 GB)
This lower-priced add-on is only available for the customers who purchased at least one Dynamics 365
Business Central Database Capacity (100 GB) add-on.
Dynamics 365 Business Central Additional Environment Add-on
The Storage capacity, by source section shows how much capacity is available by default, how much extra
capacity is added with user licenses, and how much additional capacity was specifically purchased via CSP.

NOTE
Since July 1, 2021, along with introduction of lower-priced capacity add-ons and per-license capacity quota extensions,
the capacity occupied by the files or Blob data stored in the Business Central database (the content of the Tenant Media
and Tenant Media Thumbnails tables) is counted towards the overall database storage capacity of the customer (tenant).

Storage usage by environment


The Storage usage by environment section of the Capacity page provides a tenant-level view of where your
organization is using storage capacity. Here you can see how much database storage is used by each
environment. For each of your environments, you can also navigate to the Table Information page within
Business Central, which let's you see the distribution of data size across tables.
The content of all non-system tables is counted towards the Database usage storage.
IMPORTANT
When you uninstall extensions, you have a choice of deleting or leaving the extension data in the database. If you decide
not to delete the data when uninstalling extensions, this data will be counted in the overall database storage you use.

Exceeding capacity quota


Exceeding the paid database storage limit won't interrupt transaction processing within the existing
environments. The existing environments that organically grow and eventually exceed the quota will still be
accessible and available for the customers to continue their business operations. You won't be automatically
charged for the extra storage occupied by these environments.
However, once the capacity limits are exceeded, the customers won't be able to create new environments or
copy their existing environments until the storage used by the existing environments is decreased to fit the
quota or additional capacity is purchased. These operations will also be blocked for the customers who have
more environments than they're entitled to, according to their subscription and purchased environment add-
ons.

Reducing data stored in databases


There are a few things that you can do to reduce the amount of data stored in a database to keep it under its
current limit. For more information, see Reducing Data Stored in Databases.

See also
Working with Administration Tools
The Business Central Administration Center
Managing Environments
Managing Apps
Updating Environments
Managing Tenant Notifications
Introduction to automation APIs
Manage Tenant-Specific Notifications
2/6/2023 • 8 minutes to read • Edit Online

You can get notified of administrative events that occur on environments in a Business Central online tenant. For
example, we send notifications when a major update is available for environments, when an environment
update has succeeded or failed, or when extensions require changes to be compatible with an upcoming update.
When these and other similar events occur on the tenant, an email is sent to the notification recipients for the
tenant.

NOTE
If a prospect has signed up for a trial of Business Central, make sure that they understand that they must sign up for
notifications. This is especially important if the prospect moves to My Company so that the tenant will expire after 30
days. For more information, see Dynamics 365 Business Central Trials and Subscriptions in the business functionality
content for Business Central.

Communication channels
Environment lifecycle events are communicated through various channels, each with their own benefits.
Email notification
Notifications are sent to all email addresses that are listed in the Notification recipients list of the Business
Central administration center. Manage the list manually by adding and removing recipients to ensure the right
individuals are notified of the event.

NOTE
It is important that at least one administrator's email address has been entered as a notification recipient to ensure
proper awareness of events requiring administrative attention.

IMPORTANT
To not miss update notifications from Microsoft, you must verify that the emails are not redirected to a spam folder by
your email software. The notifications are sent from the Microsoft account, no-reply-dynamics365@microsoft.com .

Microsoft 365 Message Center


Most environment lifecycle events that emails are sent for will soon also be posted to Microsoft 365 Message
Center. Over time, emails that are sent to the specified notification recipients will be a subset of the messages
that are posted in Message Center. Eventually, emails sent to notification recipients will be deprecated.
Already now, we warmly recommend that you make sure that the relevant people sign up to receive email
notifications from the Message center. For more information, see the article Message center in the Microsoft
365 admin content.
If you're a delegated admin, you might not be able to sign up yourself. In those cases, ask the internal admin to
add you or a group email account as recipients. Also, in some scenarios where your organization manages
multiple tenants, you might want to use the service communications API in Microsoft Graph to access the health
status and message center posts about Business Central. For more information, see Access service health and
communications in Microsoft Graph.
Microsoft 365 Service Health Dashboard
Both as an internal admin and as a delegated admin, you can help users determine the cause of their problems
in different ways before you have to escalate the issue to Microsoft Support. The starting point is the Business
Central administration center where you can access telemetry for the tenant and check the status of already
reported outages. For more information, see Managing Production and Sandbox Environments in the Admin
Center.
The Microsoft 365 admin center provides an overview of service health across Microsoft services. Select
Preferences to receive service health email notifications about incidents across Business Central, Microsoft
365, and other Microsoft services. For more information, see How to check service health. If you manage more
than one tenant, see View service health for all accounts.
As a partner, use the Partner Center to get an overview of service health for each customer. For more
information, see Check service health for a customer in the Partner Center content. You can also use APIs for
automated service notifications for Azure Insights & Office 365 service communications.
Telemetry in Application Insights
Application Insights telemetry includes the most complete list of Environment Lifecycle events, and can better be
used for automation and reporting purposes than the other communication channels.
Learn more about Environment Lifecycle trace telemetry here.
Customize notifications and automation
Azure Logic Apps and Power Automate have built-in connectors to query telemetry in Application Insights that
you can use to set up custom notifications or to automate certain actions triggered by an environment lifecycle
event.
Learn more about alerts on telemetry events here.
Ex a m p l e : G r o u p e d n o t i fi c a t i o n fo r a v a i l a b l e u p d a t e s

This Logic App runs every number of days (specified in deployment) and lists all updates made available to
environments that emit telemetry to the specified Application Insights resource for the specified period.
Administrators can use this to replace the many email notifications they would receive for each individual
enviroment when set up as notification recipient.

Ex a m p l e : N o t i fi c a t i o n fo r d e l e t e d e n v i r o n m e n t

This Logic App queries Application Insights every number of minutes (specified in deployment) and notifies a
user (also specified in deployment) of any deleted environments in Microsoft Teams. The action that sends the
notification in Teams can be updated to notify a Channel or Group Chat instead.

Ex a m p l e : Ta k e a c t i o n o n fa i l e d e n v i r o n m e n t u p d a t e s

This Logic App runs a query that returns any failed environment updates ever number of hours (specified in
deployment). Customize the Logic App after deploying to action the failed update, for example by opening a
case in Dynamics 365 Customer Service using the Dataverse connector.

Ex a m p l e : P o st a d a p t i v e c a r d s i n Te a m s fo r e a c h a v a i l a b l e e n v i r o n m e n t u p d a t e

This Logic App queries Application Insights every number of minutes (specified in the deployment) and posts an
adaptive card to a specified Microsoft Teams channel for each environment that has an update available. Based
on the user's choice, the Logic App will call the Business Central admin center API using an authorized service-
to-service Azure Active Directory app (configuration details specified in the deployment). The adaptive card
gives the user four choices:
Schedule the update as soon as possible ("Run Now"), and allow the update to start outside of the update
window for the environment
Reschedule the update to a specified other day
Ignore information about the update and close the card
Open the admin center

Reporting
To help you analyze Business Central telemetry, find the Power BI app in Microsoft AppSource. This app includes
an Administration report which shows an inventory of environments including various environment operations
details built with the environment lifecycle telemetry in Application Insights. Learn more here, or get it
immediately from Microsoft AppSource.

NOTE
The Power BI reports and dataset that make up this app are available on the Business Central BCTech repository on
GitHub. You can customize those resources for your own needs and publish from Power BI desktop.

Admin center operations page


The operations page does not notify you of environment lifecycle events, but does provide some details on
these operations that are not available in other channels, like the email address of the user that executed an
operation. Learn more here.
Overview of communication channels
The following table illustrates how we communicate about the different environment lifecycle events and other
communication scenarios on the different channels.

T EN A N T A DM IN
M IC RO SO F T 365 M IC RO SO F T 365 C EN T ER
A P P L IC AT IO N EM A IL M ESSA GE SERVIC E H EA LT H O P ERAT IO N S
- IN SIGH T S N OT IF IC AT IO N C EN T ER [ 1] DA SH B O A RD PA GE

Environment
Created

Update Available

Update
Scheduled

Updates
Postponed/Resu
med

Update Started

Update
Succeeded/Failed
[2]

Environment
Hotfix
T EN A N T A DM IN
M IC RO SO F T 365 M IC RO SO F T 365 C EN T ER
A P P L IC AT IO N EM A IL M ESSA GE SERVIC E H EA LT H O P ERAT IO N S
- IN SIGH T S N OT IF IC AT IO N C EN T ER DA SH B O A RD PA GE

Environment
Restart

Environment
Started/Stopped

Environment
Copy

Environment
Restore

Environment
AAD Tenant
Move

Cancel Session

Database Export Export History


Page

Environment
Setting Change
[3]

Environment
Deleted

Environment
Renamed

AppSource App
Install/Update
Scheduling

AppSource
App/PTE
Install/Update

AppSource App
Uninstall
Scheduling

AppSource
App/PTE
Uninstall

AppSource
App/PTE
Dependency
Install & Update
Orchestration
T EN A N T A DM IN
M IC RO SO F T 365 M IC RO SO F T 365 C EN T ER
A P P L IC AT IO N EM A IL M ESSA GE SERVIC E H EA LT H O P ERAT IO N S
- IN SIGH T S N OT IF IC AT IO N C EN T ER DA SH B O A RD PA GE

Installed PTE
incompatible
with next version

Service Incidents
and Advisories

Feature Change
and Deprecation
Announcements

Messages for environment lifecycle events are coming to Microsoft 365 Message Center soon.
2

Application Insights and Operations page include full failure details, email notification and Message Center
cover fewer failure reasons but include mitigation steps.
3

Examples of setting changes include changes to the environment update window, assigned security groups, and
Application Insights settings.

Notification of blocked updates


Microsoft updates environments according to the update windows that are defined for the environment in the
Business Central administration center. However, if the environment includes an app that isn't compatible with
the next version, Microsoft pauses the update and sends a notification of the issue.
After a while, all users see an in-product notification, which may confuse some people. But Microsoft wants to
update the environment, so an admin must disable and remove the problematic app so that the update can
continue. After more than a month of waiting, Microsoft sends a more strongly worded notification. If the
environment is still blocked from getting the update after more than 4-5 months, Microsoft uninstalls the
problematic app, but doesn't delete any data. The environment is updated with the latest security and other
updates.
The following list illustrates a typical timeline:
10 weeks of emails sent to the registered notification recipients.
If the update fails, Microsoft reschedules automatically. The notification recipients will receive multiple
emails. If no notification recipient has been set up, then no email is sent.
Six weeks with in-product notifications that encourage users to contact their admin.
This notification currently indicates that the environment will expire to worry users so they try to find
their admin to sort out things.
One month of more explicit in-product notifications
This notification currently indicates that the environment is missing an important update and is blocked.
The wording has been chosen to make it clearer what the issue is and what the user must do as quickly as
possible.
If the problematic app hasn't been uninstalled at this point, Microsoft typically starts the process of force-
uninstalling apps, including per-tenant extensions. Data isn't deleted.
For more information about updates, see Major Updates and Minor Updates for Business Central Online. For
more information about how to keep your Business Central compliant with upcoming updates, see Maintain
AppSource Apps and Per-Tenant Extensions in Business Central Online.

Cleaning up settings
If you end the relationship with a customer where you have set up your email address as a notification recipient,
you must remove the email address while you still have access to that customer's Business Central
administration center.

See also
Managing Updates in the Business Central Admin Center
The Business Central Administration Center
Managing Environments
Introduction to automation APIs
Working with Administration Tools
Managing Updates in the Business Central Admin
Center
2/6/2023 • 5 minutes to read • Edit Online

Business Central environments are updated according to the Business Central roadmap with two major updates
in April and October each year, and monthly, minor updates. For more information, see Major Updates and
Minor Updates for Business Central Online and the Dynamics 365 Release Plans.
Updates of the base application and platform are managed by Microsoft. As an internal administrator or as a
partner, you use the Business Central administration center to specify the timing of updates for each
environment and who receives notifications of when an update is available. You can also help prepare your
solution and your users by creating preview environments so that you can get acquainted with new functionality
in the product. For more information, see Major Updates and Minor Updates.

Set the update window for each environment


The update window for an environment defines the hours during the day for the selected time zone in which the
environment can be updated. When an update is rolling out—monthly or major update—it will be applied to an
environment within the time frame that the update window defines.
This window helps ensure updates are applied outside of the normal business hours of the organization. Every
environment has a default update window that's between 8:00 PM and 6:00 AM local time for the environment's
country. In countries that have multiple time zones, the system sets a time zone that's close to the geographic
center of the country as default.

NOTE
Desktop users who are signed in during the update will receive an alert in Business Central before the update starts.

To change the update window for an environment:


1. On the Environments tab of the Business Central administration center, choose the Name of the relevant
environment to open the environment details.
2. Choose the Update Settings action, and then choose the Set update window action.
3. In the Set update window pane, specify the time zone, start time, and end time, for the update window for
the environment. The update window must be a minimum of six hours.
4. Choose Save .
This timeslot now becomes the default window when updates will be applied to this environment.

Schedule an update date


Once an update is available, you can choose a specific date that each environment is updated.
The following fields on the environment page can help you plan the update:

F IEL D DESC RIP T IO N


F IEL D DESC RIP T IO N

Available Update Version Specifies the version to which you can update your
environment

Update Scheduling Available Specifies whether it's possible for you to change the update
date. The options are Yes or No .

Scheduled Update Date Specifies the default update date set by Microsoft. You can
change this date to one you prefer, if Update Scheduling
Available is set to Yes

Update Window (UTC + offset) Specifies the hours of the day that an update can run. (UTC
+ offset) indicates the time zone, represented as
Coordinated Universal Time plus or minus the difference in
hours and minutes.

Update Rollout State Microsoft can sometimes postpone the updates for various
reasons. This field provides information that can help you
track the current state of the rollout. For more information
about what happens in such cases, see Postponed updates

IMPORTANT
If you don't set a date in the Scheduled Update Date field, Microsoft will update the environment automatically on any
day between the default date and the date that is shown as the last possible update date in your notification email. If you
don't want your environment to be updated automatically, change the update date to one that fits you better.

For more information, see Schedule updates.


To schedule an update date:
1. On the Environments tab of the Business Central administration center, choose the Name of the
relevant environment to open the environment details.
2. Choose the Update Settings action, and then choose the Set update date action.
3. In the Schedule Environment Update pane, specify the update date.

NOTE
You can choose to ignore the environment's update window when scheduling a specific update by switching
Allow the update to run outside the update window to Yes . If an update is scheduled for the same day,
this option lets it start immediately, and it lets large upgrades run for longer than 24 hours if required.

4. Choose Schedule Update .


If an administrator hasn't picked a date for an update, then the update is applied automatically within a default
date range. The default date range is communicated in advance to tenant administrators through administrative
notifications. You can then choose to override that with a custom date by following the steps that are provided
above. Not selecting an update date doesn't prevent the environment from being updated.

Get notified of updates


For updates that tenant administrators can schedule, a notification is sent to all notification recipients that are
listed on the Notification recipients tab of the Business Central administration center. For more information,
see Managing Tenant Notifications.

IMPORTANT
To not miss update notifications from Microsoft, you must verify that the emails are not redirected to a spam folder by
your email software. The notifications are sent from the Microsoft account, no-reply-dynamics365@microsoft.com .

For versions earlier than 2021 release wave 1, admins can't schedule the monthly minor updates. Until such
environments are updated to version 18.0 and later, the update is applied to tenant environments as it becomes
available. No notifications are sent to tenant administrators prior to the update. Notifications are sent only after
the update is applied.

Environments that can't get updated


Sometimes an environment can't get the new update. For example, a per-tenant extension might conflict with
the changes in the new version of the base application.
Before a major update, Microsoft routinely checks per-tenant extensions in all existing environments for
compatibility with the next major update. If we detect compatibility issues with the upcoming version, we send
email notifications that describe the detected issues to the notification recipients. We warmly encourage all
admins to review these emails and take action as soon as possible.
Ifyou discoverany such issues, apply the changes to your solution as usual using Visual Studio Code. Test the
new appin a sandbox environment that runson the new major version, either in preview or the official version. If
testscomplete successfully, upload the new app version into your production environment in the Extension
Management page, setting theDeploy to field toNext major version .This way the compatible version of your
app will beusedwhenyour environment is updated.For more information, see Deploying a Tenant Customization.
For more information, see Failed updates and rescheduling.

See also
Major Updates of Business Central Online
Prepare for major updates with preview environments
Working with Administration Tools
The Business Central Administration Center
Managing Environments
Managing Tenant Notifications
Introduction to automation APIs
Managing Sessions in the Admin Center
2/6/2023 • 2 minutes to read • Edit Online

For each environment in the Business Central administration center, you can use the Manage Sessions page to
view information about active sessions on an environment and cancel selected sessions.
To open the page, select Manage Sessions . Use the Show session details check box to show more or fewer
details.

Cancel sessions
Canceling a session is sometimes the only way to unblock a customer. For example, a long-running report is
locking data in a table, preventing warehouse employees from working.
To cancel a session, select it from the list and then select Cancel selected sessions .

Restart environment
In some cases, canceling the sessions does not solve the problem. In those cases, you may want to restart the
environment.
To restart an environment that is causing problems for you, go to the Manage Sessions page, choose the
relevant environment, and then choose the Restar t Environment action.

IMPORTANT
Make sure that all users are signed out of all companies in the environment before you restart it.

See also
Managing Tenant Notifications
Managing Apps
Updating Environments
Rename Environments
Restoring an Environment
Move an Environment to another Azure Active Directory organization
Introduction to automation APIs
Copy a Production or Sandbox Environment in the
Admin Center
2/6/2023 • 4 minutes to read • Edit Online

INTRODUCED IN: Business Central 2021 release wave 2

You can create an environment that is a copy of an existing environment, such as a sandbox that is based on
production for troubleshooting, or a production environment that is based on a sandbox, for example. When
you create an environment as a copy of another environment, the new environment is created on the same
application version as the environment that you are copying. The new environment will contain all per-tenant
extensions and AppSource extensions that are installed and published in the original environment that is being
copied.

To copy an environment
1. In the Business Central administration center, select Environments , then select the environment that you
want to copy.
2. On the Environment Details page, choose the Copy action.
3. In the Copy environment pane, specify the type of environment that you want to create based on the
current environment.
4. Specify a name for the new environment.
5. Choose the Create action.
When the process starts, you can go to the list of your environments and see the status of the new environment.
At first, you'll see the new environment with the state Preparing , and then Active once the new environment is
fully up and running. Further status details of the copy operation can be found on the Operations page. The
original environment that the new environment is based on remains active.

Environment copies
When an environment is created as a copy of another environment, a number of precautions are taken for that
copy:
Tasks in the job queue are automatically stopped
To see which scheduled jobs are stopped, and to decide which jobs to restart in the new environment, go
to the Scheduled Tasks page in Business Central. There, you can set tasks to be ready to run in the job
queue. However, only tasks that are marked as belonging to the current environment can run. For more
information, see View Scheduled Tasks in the business functionality content.
Any base application integration settings are cleared
Any irreversible features that were enabled in the original environment will also be turned on in the copy.
For more information, see Features that can't be turned off.
Development extensions that are published from AL-Go for GitHub or Azure DevOps and any extensions
that depend on them are uninstalled when the source environment is a sandbox. Any data that was
created in the original environment by the extensions that are now uninstalled in the copy will not be
deleted. Any updates to per-tenant extensions that are slotted to be upgraded with the next minor or
major upgrade will be retained.
Outbound HTTP calls from extensions are blocked by default and must be approved for each extension,
otherwise instead of an external call, the system will display the following error message: The request
was blocked by the runtime to prevent accidental use of production services.
To enable outbound HTTP calls, go to the Extension Management page in Business Central, and choose
Configure . Then, on the Extension Settings page, make sure that Allow HttpClient Requests is
selected. This setting must be enabled for each extension, including libraries.
Any General Data Protection Regulation (GDPR) action must be handled separately and repeated for the
environment. There is no synchronization with the original environment after the copy has been created.
The internal administrator has the same tools and responsibilities for the copy as they do for the original
environment. As a data processor, Business Central offers the same level of data protection and data
handling restrictions to all types of environments, both sandboxes and production environments.
The following setups are set to status disabled
Doc. Exch. Service Setup
Curr. Exch. Rate Update Setup
VAT Reg. No. Srv Config
Graph Mail Setup
CRM Connection Setup
CDS Connection Setup
All records in the Service Connection table
All records in the Exchange Sync table
The following data is cleared
Password in the OCR Service Setup table
SMTP Server in SMTP Mail Setup
Exchange Service URL in the Marketing Setup table
The following changes are made for first-party extensions
AMC Banking 365 Fundamentals
The Service URL in AMC Banking Setup is reset to default for Sandbox environments
Email - Outlook REST API
All email accounts of types "Microsoft 365" and "Current User" are deleted. Deleting these
records turns any existing field monitoring setup non-valid.
Email - SMTP Connector
SMTP Server details are deleted
The following changes are made for specific localizations
Spain
SII Setup is set to disabled
United Kingdom
Password in GovTalk Setup table is deleted
Netherlands
All Digipoort related fields in the Elec. Tax Declaration Setup table are cleared

See also
Managing Production and Sandbox Environments in the Admin Center
Managing Tenant Notifications
Managing Apps
Updating Environments
Managing Sessions
Rename Environments
Restoring an Environment
Move an Environment to another Azure Active Directory organization
Introduction to automation APIs The Business Central Administration Center
Rename Environments in the Admin Center
2/6/2023 • 4 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

NOTE
This feature is in preview. It might change or be removed in the future updates.

You can change the name of any environment. The name uniquely identifies the environment from your other
environments. Before you change a name, you must consider that the name also is part of the environment's
URL. The URL is used in links to the environment in various ways. So changing the name can have significant
impact.
The renaming of an environment is logged and shown in the operations log.

Before you rename an environment


Read the Environment rename considerations section to understand the consequences of renaming an
environment.
Make sure you notify all your users, including any external service integrations you may have, about the
upcoming URL change. It will let them prepare to update their references.
Determine the best time to do the renaming. Renaming an environment requires a restart to the
environment. We recommend doing this operation when no users are active in Business Central.

To rename an environment
1. Select Environments , then select the environment you want to rename.
2. On the Environment Details page, select Rename .
3. On Rename environment page, read the information.
4. Enter the new name, and then select Rename .
5. Confirm your intent to rename the environment.
At this point, the environment state will first change to Preparing | Rename Scheduled , then to Active again
when the rename has been completed. The new name will be available immediately. The environment will no
longer be accessible using the old environment name.
You can also review the log for the Rename operation on the Operations page afterwards.

Environment rename considerations


Changing the environment name can affect many scenarios and integrations. In the early stages of a customer
implementation, it may be a low risk operation. But renaming an environment that's been used by customers for
a while or integrated with many external services and components is risky. So carefully plan for it.
Here are some areas where the environment name is used, which will be affected when you change the
environment name. Consider these areas and plan your communication before attempting to rename an
environment:
Web client URL, including links to web client bookmarked by users
Deep links to specific pages within Business Central created by users or shared by them via e-mails,
internal documentation or training portals, Teams channels, Word, and Excel documents. They're often
exchanged among users in the same company, across companies, across environments, across tenants.
Links created by users as desktop shortcuts. Links sent or created before the name change will no longer
work after the name change.
Integrations that embed the web client, for example, SharePoint apps composed of Business Central
pages
Integrations that launch the web client
Partner-developed mobile apps, web applications, and so on. These apps likely originate from partners
outside the customer's organization where the admin can't update URLS.
Mobile apps, including Windows 10 store app for desktop/tablet. Affects only users who have modified
the protocol handler to force the app to connect to environment with name other than "production". If the
user keeps working with "production" on the mobile app (which is default now), and the admin renames
the environment from "prod2" to "myprod", the mobile user isn't affected. Otherwise, the app would
throw an error, and the user would have to exit using a newly created protocol handler link.
Browser cache. Business Central stores the URL, including environment name, in some of its cached data.
This data is cached browser-side, that is, in the user's browser and across devices. Admins typically don't
have access or control this data cache. When users lose their cache, they lose the link modifications to all
their pages and preferences.
Web services URL, potentially affecting external integrations that use OData or SOAP
Business Central add-ins and integrations with other Microsoft services
Outlook Add-in. The Add-In manifest that is saved to Exchange Server, either per-organization or per-
user, includes the environment name.
Excel Add-in. Each user's Excel worksheet stores the environment name.
Power BI. All reports, including the default reports deployed from the Role Center, built before the
rename will be affected. Also, Power BI apps installed before the rename would be affected. There's no
automatic way to repair these items. The partner or user would have to manually update the
connections.
Power Apps/Automate. All apps and flows built before rename would be affected with no automatic
way to repair. The partner or user would have to manually update the connections.
CDS. CDS Virtual Entity setup stores environment name.
Development scenarios
Publish to sandbox environment from Visual Studio Code. The launch.json file of extensions might
contain the sandbox name, if different from "default". The files require source code updates.
CI/CD pipelines for test and deployment could be impacted by environment renames.
Azure Application Insights logs and metrics

See also
Managing Tenant Notifications
Managing Apps
Updating Environments
Rename Environments
Restoring an Environment
Move an Environment to another Azure Active Directory organization
The Business Central Administration Center
Introduction to automation APIs
Exporting Databases in the Admin Center
2/6/2023 • 6 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

From the Business Central administration center, you can export the database for Business Central online
environments as BACPAC files to an Azure storage container.

Considerations before you begin


You can only request a database export for production environments. If you want to export data from a
sandbox environment, you can use Excel or RapidStart.
You can only request a database export if the customer has a paid Business Central subscription.
You must have explicit permission to export databases. For more information, see the Users who can export
databases section.
You can't export your database to an Azure premium storage account. The steps in this article are only
supported on Azure standard storage accounts.

NOTE
For each environment, you can export the database a maximum of 10 times per month. You can see the number of
exports still remaining for the current month in the Create Database Expor t pane when creating the export file.

Setting up Azure storage


Before you can export the file, you must first set up the Azure storage account container that the BACPAC file will
be exported to.
Creating the storage account
The first step is to create an Azure standard storage account, if you don't already have one. To set up the export,
you must first have a subscription to Microsoft Azure and access to the Azure portal.
For more information setting up an Azure storage account, see Create a storage account.
Generating a shared access signature (SAS )
The next step is to generate a shared access signature (SAS) that provides secure delegated access to your
storage account. Business Central uses the signature to write the BACPAC file to your storage account.
To generate a shared access signature (SAS)
1. On the Azure storage account, choose Shared access signature in the navigation pane.
2. In the Allowed ser vices section of the shared access signature pane, select Blob , and clear the other
options.
3. In the Allowed resource types section, select Container and Object , and clear the other options.
4. In the Allowed permissions section, mark Read , Write , Delete , and Create , and clear the other
options.
5. Select a start and end date and time for the SAS. A minimum expiration window of 24 hours from the
initiation of the export is required.
TIP
It is a best practice to use near-term expiration for the account's SAS. To reduce risk of a compromised storage
account, set the end date and time no later than what is needed for you to complete the database export
operation. However, the SAS must be valid for a minimum of 24 hours.

6. In the Allowed protocols section, select HTTPS only .


7. Select Generate SAS and connection string .
8. Copy the Blob ser vice SAS URL .
For more information on generating and using a SAS, see Grant limited access to Azure Storage resources using
shared access signatures (SAS).

Creating the database export


When you've created the Azure storage account and generated the SAS URI, you can then create the export file
from the Business Central administration center.
1. On the Environments list page, choose the relevant production environment to view the environment details.
2. On the action ribbon of the environment details, choose Database , and then choose Create Database
Expor t .
3. In the File Name field, specify a name for the export file, or leave the default value.
4. In the SAS URI field, specify the Blob ser vice SAS URL value that you copied in the previous section.
5. In the Container Name field, enter the name of the container in the Azure storage account to which you
want the BACPAC file exported. If you've already created a container in your Azure storage account, you can
enter the name of that container here. Otherwise, if the name that is specified in the Container Name field
doesn't already exist in the Azure storage account, it will be created for you.
Once the export operation begins, the BACPAC file is generated and exported to the indicated Azure storage
account. The operation may take several minutes to several hours depending on the size of the database. You
can close the browser window with the Business Central administration center during the export. When the
export completes, you can access the export file in the defined container in your Azure storage account.
Optionally, you can import the data into a new database in Azure SQL Database or SQL Server for further
processing. For more information, see Quickstart: Import a BACPAC file to a database in Azure SQL Database.

Viewing the export history


All database export activity is logged for auditing purposes. To view the history, choose Database , then choose
View Expor t Histor y on the environment details page of the environment.

Users who can export databases


Permission to export databases is limited to specific types of users: internal and delegated administrators. The
following users are allowed to export databases.
Delegated administrators from reselling partners
Administrators from the organization that subscribes to Business Central online
Also, these users must have the D365 BACKUP/RESTORE permission set assigned to their user account in the
environment they're trying to export.
For more information about permissions sets and user groups, see Assign Permissions to Users and Groups.
Using the exported data
The BACPAC file contains data that is customer-specific business data. Technically, Business Central online is a
multitenant deployment, which means that each customer tenant has their own business database while the
data that defines the application is in a shared application database.
This means that if you want to export the data in order to change the customer's Business Central from an
online deployment to an on-premises deployment, you must also get the application data from the installation
media from the same version of Business Central that the online tenant is using. You can see the version number
in the Business Central administration center or the Help and Suppor t page in the customer's Business
Central.

IMPORTANT
While you can import the downloaded BACPAC file into your own SQL Server instance, Microsoft does not provide
support for creating a working on-premises environment from the BACPAC that you download from Business Central
online.

For more information, see Quickstart: Import a BACPAC file to a database in Azure SQL Database, Migrating to
Single-Tenancy From Multitenancy, and When to choose on-premises deployment.

NOTE
If you are getting an error saying your file contains corrupted data when importing the bacpac file please ensure you are
using the .NET Core version of SqlPackage.exe.

Restoring the exported data to Business Central online


If you decide at some point that you want to restore the exported data to a new environment in Business Central
online, then you must go through the same steps as you went through to migrate from on-premises to Business
Central online. This way, you can prepare the database so that it's ready to migrate to the latest version of
Business Central. For example, you could choose to replicate the data to a sandbox environment for further
testing and training. For more information, see Migrating On-Premises Data to Business Central Online.

Restoring the exported data to a container


If you want to use the exported data in a container-based developer environment, you can use Windows
PowerShell scripts to help you do that, including the BCContainerHelperPowerShell module.

See also
SQL Server technical documentation
Quickstart: Import a BACPAC file to a database in Azure SQL Database
Delegated Administrator Access to Business Central Online
Working with Administration Tools
The Business Central Administration Center
Managing Environments
Updating Environments
Managing Tenant Notifications
Introduction to automation APIs
Restoring an Environment in the Admin Center
2/6/2023 • 7 minutes to read • Edit Online

As an administrator, you can restore an existing environment from a time in the past, within the retention period
that applies to both production and sandbox environments.
Database backups are an essential part of any business continuity and disaster recovery strategy, because they
protect your data from corruption or deletion. Business Central online uses Azure SQL Database as the
underlying database backup technology for its environments. All databases are protected by automated backups
that are continuously created and maintained by the Azure SQL service. For more information, see Databases
and backups.

Users who can restore environments


Permission to restore environments is limited to specific types of users: internal and delegated administrators.
The following users are allowed to restore environments.
Delegated administrators from reselling partners
Administrators from the organization that subscribes to Business Central online
Also, these users must have the D365 BACKUP/RESTORE permission set assigned to their user account in the
environment they're trying to export.
For more information about permissions sets and user groups, see Assign Permissions to Users and Groups.

Considerations and limitations


Environments can only be restored if the customer has a paid Business Central subscription.
Each environment can be restored up to 10 times in a calendar month.
An environment can only be restored within the same Azure region and country (Business Central
localization) as the original environment.
A production environment can be restored to an environment of type Production or Sandbox . A sandbox
environment can only be restored to a Sandbox environment.
When restoring a sandbox environment, all development extensions (that is, extensions published directly
from Visual Studio Code) won't be available in the restored environment—even if they were present at the
point-in-time you're restoring to). Additionally, any per-tenant extensions that depend on such development
extensions will also not be available.
Per-tenant extensions you may have uploaded that target the next version of the Business Central won't be
available in the restored environment—even if they were uploaded at the point-in-time you're restoring to.
Per-tenant extensions that were already installed will be available in the restored environment.
Every AppSource and Business Central app in the restored environment will have the latest available hotfix
installed automatically—even if the hotfix was introduced after the point-in-time you're restoring to.
Azure Active Directory app registration, status, and permissions in the environment will be restored to their
state at the time you are restoring to. Apps that were authorized in the Business Central administration
center will not be restored even if their permissions in the restored environment are.
The update window and application insights connection string that are specified for the source environment
in the admin center at the time when the restore operation started will be retained on the target
environment. The target environment will not be restored to the values for these settings that existed on the
source environment at the time that the source environment is being restored to.
The following setups are set to status disabled
Doc. Exch. Service Setup
Curr. Exch. Rate Update Setup
VAT Reg. No. Srv Config
Graph Mail Setup
CRM Connection Setup
CDS Connection Setup
All records in the Service Connection table
All records in the Exchange Sync table
The following data is cleared
Password in the OCR Service Setup table
SMTP Server in SMTP Mail Setup
Exchange Service URL in the Marketing Setup table
The following changes are made for first-party extensions
AMC Banking 365 Fundamentals
The Service URL in AMC Banking Setup is reset to default for Sandbox environments
Email - Outlook REST API
All email accounts of types "Microsoft 365" and "Current User" are deleted. Deleting these
records turns any existing field monitoring setup non-valid.
Email - SMTP Connector
SMTP Server details are deleted
The following changes are made for specific localizations
Spain
SII Setup is set to disabled
United Kingdom
Password in GovTalk Setup table is deleted
Netherlands
All Digipoort related fields in the Elec. Tax Declaration Setup table are cleared

Before you restore an environment


Here are a few important things to do when you're planning to restore an environment:
Make sure you communicate the plan to restore an environment within your organization upfront, in
good time.
Typically, you want to stop users and external integrations from using the environment during
restoration. Consider doing the following actions in the environment you're planning to restore:
Remove access to the environment for non-essential users, but make sure required users, like
administrators, keep access. For more information, see Remove a user's access to the system.
Put all job queues to on hold. For more information, see Use Job Queues to Schedule Task.
Consider renaming the environment. The users and external integrations won't be able to access it by its
old name.
When restoring an environment, you'll create a new environment that the database backup will be
restored to. You can't use the same name for two environments of the same customer. So if you want the
restored environment to have the same name as the original environment, rename the original
environment before you run the restore operation. For example, you could change the name to include
DONOTUSE .
For more information, see Rename Environments in the Admin Center.

Restore an environment
To restore an environment, you'll have to provide a name for the environment and a date/time from which to
restore the database.
1. Select Environments and then open the environment you want to restore.
2. Select Restore .
3. In the Restore Environment pane, specify the date and time in the past to which you want to restore
the environment.
4. Select the type to be used for the restored environment.
5. Specify a name for the restored environment.
6. Select Restore .

NOTE
For newly created environments it may take up to 30 min for the backups to be initialized, so you may not be able
to restore an environment if you have just created it.

7. When the process starts, you can go to the list of your environments and see the status of the restored
environment. At first, you'll see the new environment with state Preparing . The original environment
state remains as Active .
The restore operation duration is affected by several factors. For large or highly active databases, the restore
might take several hours. You can find more details about the factors that affect the recovery time at Recovery
time.
Once the restore is completed, the environment state will change to Active . If the restore operation fails, you
can find the failure details on the Operations page. In this case, delete the failed environment, and then try to
restore again. Contact Microsoft Support if the issue persists.

After you restore an environment


After restoring an environment, you should inspect and adjust data to prepare it for users. Consider enforcing
these steps during this period:
Remove access to the environment for non-essential users, but make sure required users, like administrators,
keep access.
Put all job queues in the restored environment to on hold immediately after restore. For more information,
see View Scheduled Tasks in the business functionality content.
If needed, you can upload the per-tenant extensions targeting the next version of Business Central again.
The original environment will remain available and isn't affected by the restore operation. You can then get back
to the original environment if you need to look up data. Or maybe you'll have to migrate some data to the
restored environment. You can, for example, migrate data by using Business Central RapidStart services. For
more information, see Migrate Customer Data.
IMPORTANT
You can restore your production environment into a new production environment even if doing so results in exceeding
your number of environments or database capacity quotas. You can however only exceed this quota by one extra
production environment, regardless of how many production environments you have available for your subscription. This
capability is provided as an exception, to ensure that you can always restore your production environment in critical
situations. You must return within your quota within 30 days following the restore by either removing the original
production environment or by purchasing an additional production environment. Before removing the environment, we
recommend you export the environment to an Azure storage container in case you need to access some data at a later
point. This exception isn't available for restoring from and to sandbox environments.

When you're satisfied with the data in the restored database, enable the users, start the job queues, and let your
organization know that the restore process is now completed and they can again use the environment.

See also
Managing Tenant Notifications
Managing Apps
Updating Environments
Rename Environments
Restoring an Environment
Move an Environment to another Azure Active Directory organization
The Business Central Administration Center
Introduction to automation APIs
Service Overview for Business Central Online
Move an Environment to another Azure Active
Directory organization
2/6/2023 • 3 minutes to read • Edit Online

In some cases, the Azure Active Directory (Azure AD) organization (also known as the Azure AD tenant) of a
Business Central customer changes after they acquire a Business Central environment. This situation can occur
for various reasons, such as the following:
Business entities merge.
An acquisition takes place.
The customer decides to use one Azure AD tenant in a specific region and stop using Azure AD tenants they
created in other regions.
The environment was mistakenly created by the reselling partner for the wrong Azure AD tenant.
In all such cases, the customers want to preserve the Business Central environments they created for the
original Azure AD tenants, and link them to the new ones instead. Microsoft Support can move an environment
from one Azure AD tenant to another, based on a support request.

Request to move an environment


As a partner, you can submit a support request to Microsoft Support by following the guidance at Escalating
support issues to Microsoft. When submitting these support requests, you must provide the following
information:
Proof of your delegated admin rights in both Azure AD tenants
Confirmation from the customer that the environment move is authorized by them
You can request to move one or more environments. For Microsoft to do the move, you'll need to provide
information about the source and destination Azure AD tenants, such as:
Environments name, type and country
Source tenant ID and domain
Destination tenant ID and domain
Does the destination tenant have a valid Business Central subscription?
Does the destination tenant have enough available user licenses?
Does the destination tenant have enough environment licenses?
Does the destination tenant have enough storage available for the environments being migrated?
Once the move is completed, your environments will appear in your new tenant.

Considerations
Environment data will remain unchanged during the move operation. The exact same environment will be
linked to a specified Azure AD tenant.
The country, Azure region, and type of the environment (production or sandbox) will remain the same, and
can't be changed during this operation.
The operation will involve a downtime period for the environment being moved (typically not exceeding 2
hours). So the operation needs to be coordinated with the customer and Microsoft Support.
Business Central Support doesn't provide help with moving the Business Central subscriptions, domains, and
other resources between the Azure AD tenants. Your support representative or account manager will assist
you in contacting billing to cancel or credit your previous subscription, if needed.

Before you request your environment to be moved


If you don't have a Business Central subscription (paid or trial) in the destination tenant, you'll need to create
one. You might need to purchase a new subscription in the destination tenant (or convert a trial to paid), if
not already done.
Make sure the destination tenant meets the following requirements:
It has at least as many active user licenses as the source tenant.
It has enough Business Central environment add-on licenses to cover the environments being moved
It has at least as much Business Central storage as the source tenant.

After the environment has been moved


Users may have been added to the environment prior to the move operation, while it was still connected
to the old Azure AD tenant. If so, these users won't be migrated to the new Azure AD tenant. You'll need to
recreate the users on the target tenant if you still want them. You can add multiple user accounts at once
using Excel spreadsheet or other file saved in CSV format. After the users are created on the target Azure
AD tenant, assign them the required roles or licenses and import these users into the moved
environment.

NOTE
User personalizations will be lost.

You might need to reconfigure some add-ins, external applications, and settings after the tenant-to-tenant
migration. Some examples include the Business Central Outlook add-in, Excel add-in, Power BI, Power
Apps, Power Automate connectors, Dataverse, user personalizations, and more.

See also
Managing Tenant Notifications Managing Apps Updating Environments Rename Environments Restoring an
Environment Managing Production and Sandbox Environments The Business Central Administration Center
Introduction to automation APIs
Environment Telemetry in the Business Central
administration center
2/6/2023 • 2 minutes to read • Edit Online

The Business Central administration center provides telemetry for the tenant environments to enable
troubleshooting and support for the tenant. The Telemetry tab provides telemetry of top-level AL events, and
any errors resulting from calls through the telemetry stack.

TIP
If your users complain of a confusing error message such as Sorry, we just updated this page. Please close and reopen.,
then you can often find the underlying problem by analyzing telemetry in the Business Central administration center. For
example, in the case of the Sorry, we just updated this page. Please close and reopen. message, the underlying problem is
often that two users are trying to modify the same data. So if both users open the same sales order, and both change a
field, then one of them will see the Sorry, we just updated this page. Please close and reopen. message, because Business
Central saves changes as soon as you move to the next field or close the page.

Filter by environment
To filter the telemetry for an environment:
1. Select a base point-in-time for the timestamp of the telemetry messages.
2. Enter a number of minutes before or after the base point-in-time to set a range of time for the timestamp. A
negative number indicates a number of minutes before the base point-in-time, and a positive number
indicates a number of minutes following the base point-in-time. For example, a value of -15 filters messages
to a timestamp range of up to 15 minutes before the base point-in-time.
3. Choose the message type.
4. Choose the environment.
5. Select Filter .

Enable richer telemetry


APPLIES TO: Business Central 2019 release wave 2 and later

Get richer telemetry to help you troubleshoot by sending telemetry to Microsoft Azure Application Insights. For
more information, see Enable Sending Telemetry to Application Insights.
Application Insights is a service hosted within Azure that gathers telemetry data for analysis and presentation.
For more information, see What is Application Insights?.
For an overview of the telemetry types that are currently emitted, see Monitoring and Analyzing with Telemetry.

IMPORTANT
In Business Central 2020 release wave 2 (v17) and earlier, don't use an Azure Application Insights resource in Germany
regions, such as (Europe) Germany West Central or (Europe) Germany Nor th . If you do, traces from Business
Central might not be recorded in Application Insights. The mitigation is to create an Azure Application Insights resource in
a region outside of Germany. Then, when the relevant time comes, move the resource to the preferred region.
See also
Monitoring and Analyzing Telemetry
Enabling Application Insights
Working with Administration Tools
The Business Central Administration Center
Managing Environments
Managing Tenant Notifications
Introduction to automation APIs
The Business Central Admin Center API
2/6/2023 • 7 minutes to read • Edit Online

The Business Central administration center API enables administrators to programmatically do administrative
tasks for a Business Central tenant. With the API, administrators can, for example:
Query and work with production and sandbox environments for the tenant.
Set up administrative notifications.
View telemetry for events on the tenant.
For more information about administrative capabilities, see The Business Central Administration Center. This
article describes the API contracts for these administrative capabilities.

IMPORTANT
For delegated admin access, you must add the Azure Active Directory (Azure AD) application to the AdminAgents
group. If the Azure AD application is not added, the consent flow will show an error such as Need pre-consent. For more
information, see Pre-consent your app for all your customers in the Graph documentation.

Location
The Business Central administration center API is located at the following URL:
https://api.businesscentral.dynamics.com.

Authenticate using service-to-service AAD Apps (Client Credentials


Flow)
IMPORTANT
This authentication type is supported from version 20.0 an onwards

The Business Central administration center API supports authentication using AAD Apps.
1. Sign in to the Azure portal.
2. Register an application for Business Central administration center in your Azure Active Directory tenant.
Follow the general guidelines at Register your application with your Azure Active Directory tenant.
When you add an application to an Azure AD tenant, you must specify the following information:

SET T IN G DESC RIP T IO N

Name Specify a unique name for your application.

Supported account types Select either Accounts in this organizational


director y only (Microsoft only - Single tenant) or
Accounts in any organizational director y (Any
Azure AD director y - Multitenant) .
SET T IN G DESC RIP T IO N

Redirect URI Optional. You can grant consent from the Azure portal if
left empty.

When completed, an Over view displays in the portal for the new application.
3. Create a client secret for the registered application as follows:
a. Select Cer tificates & secrets > New client secret .
b. Add a description, select a duration, and select Add .

NOTE
Copy the secret's value for use in your client application code. This secret value is never displayed again after you
leave this page.

For the latest guidelines about adding client secrets in Azure AD, see Add credentials in the Azure
documentation.

NOTE
Copy the Application (client) ID of the registered app. You'll need this later. You can get this value from the Over view
page.

4. Grant the registered application AdminCenter.ReadWrite.All permission to the Dynamics 365


Business Central administration center API as follows:
a. Select API permissions > Add a permission > Microsoft APIs .
b. Select Dynamics 365 Business Central .
c. Select Application permissions , select AdminCenter.ReadWrite.All , then select Add
permissions .

NOTE
If you intent to use the same AAD App with the Automation API and Business Central Web Services you can also
grant API.ReadWrite.All and Automation.ReadWrite.All permissions. Learn more here.

5. (optional) Grant admin consent on each permission by selecting it in the list, then selecting Grant admin
consent for <tenant name> . This step isn't required if you'll be granting consent from the Business
Central administration center. It is possible to grant consent from this page only for your own current
tenant. This works for single-tenant apps, but for multi-tenant apps you have to grant consent for each
tenant from that tenant's Azure AD portal or the Business Central administration center
6. Go to the Business Central administration center and navigate to the 'Authorized AAD Apps' page. Paste
the Application (client) ID of your app in the form to authorize an app.
7. If not already completed in step 5 you can grant consent for your app from the 'Authorized AAD Apps'
page in the Business Central administration center.
Note: There might be a short delay until the Granted status is visible in the TAC UI after refreshing.
8. (optional) Some operations in the Business Central administration center API require that the app has a
permissions assigned in the environment in addition to the authorization in the Business Central
administration center. Follow the instructions in Task 2 here to assign permissions.
NOTE
Learn more about permissions required for App Management operations here and learn more about permissions
required for Database Exports here.

Getting an Access Token with Client Credentials Flow


HTTP requests sent to the Business Central administration center API must include the Authorization HTTP
header, and the value must be an access token.
The following examples show how to obtain such a token using PowerShell. Using C# is straightforward.
PowerShell example without prompt:

$cred = [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential]::new($AppId, $AppSecret)


$ctx =
[Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new("https://login.windows.net/$Ten
antName")
$token = $ctx.AcquireTokenAsync("996def3d-b36c-4153-8607-a6fd3c01b89f",
$cred).GetAwaiter().GetResult().AccessToken

NOTE
In the PowerShell example above, the guid specified to acquire the token (996def3d-b36c-4153-8607-a6fd3c01b89f) is
the resource ID of Business Central. The example gets the client credential using the app secret, but the recommended
way would be to rely on X.509 certificates.

Calling Business Central administration center API OAuth2Flows


After the Azure AD Application has been set up, authorized in the Business Central administration center, and
granted admin consent, you're ready to make API calls.
The following sample uses the Rest Client for Visual Studio Code. Using the Rest Client makes it easy to see
which HTTP calls are made both against Business Central and Azure Active Directory. Any HTTP client can be
used to create the requests below. Or you can choose any library, like MSAL.
@tenantId = <tenant id>
@clientId = <client id>
@clientSecret = <client secret>
@baseUri = https://api.businesscentral.dynamics.com
@scope = {{baseUri}}/.default
@url = {{baseUri}}/admin/v2.15

# @name auth
POST https://login.microsoftonline.com/{{tenantId}}/oauth2/v2.0/token HTTP/1.1
Content-type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id={{clientId}}
&client_secret={{clientSecret}}
&scope={{scope}}

### Variable Response


@accessHeader = Bearer {{auth.response.body.$.access_token}}

# @name GetEnvironments
GET {{url}}/applications/BusinessCentral/environments HTTP/1.1
Authorization: {{accessHeader}}

### Variable Response


@environmentName = {{GetEnvironments.response.body.value.[0].name}}

Setting up Azure Active Directory (Azure AD) based authentication


(Authorization Code Flow)
Sign in to the Azure portal to register your client application as an app and enable it to call the Business Central
administration center API.
1. Follow the instructions in the Integrating applications with Azure Active Directory article. The next steps
elaborate on some of the specific settings you must enable.
2. Give the application a Name , such as Business Central Web Ser vice Client .
3. For Application type , choose either Native or Web app/API depending on your scenario. The code
examples below assume Native .
4. Choose a Redirect URI . If it's a Native app, you can choose for example:
BusinessCentralWebSer viceClient://auth . If it's a Web app/API app, set the value to the actual URL of
the web application.
5. During the registration of the app, make sure to go to Settings , and then under API ACCESS , choose
Required permissions . Choose Add , and then under Add API Access , choose Select an API and search
for the Dynamics 365 Business Central option. Choose Dynamics 365 Business Central , select
Delegated permissions , and then choose the Done button.

NOTE
If Dynamics 365 Business Central doesn't show up in search, it's because the tenant doesn't have any
knowledge of Dynamics 365 Business Central. To make it visible, an easy way is to register for a free trial for
Dynamics 365 Business Central with a user from the directory.

6. Make a note of both the Application ID and the Redirect URI . They'll be needed later.
Getting an access token with Authorization Code Flow
HTTP requests sent to the Business Central administration center API must include the Authorization HTTP
header, and the value must be an access token.
The following examples show how to obtain such a token using PowerShell. Using C# is straightforward.
PowerShell example without prompt:

$cred = [Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential]::new($UserName,
$Password)
$ctx =
[Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new("https://login.windows.net/$Ten
antName")
$token =
[Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireToke
nAsync($ctx, "https://api.businesscentral.dynamics.com", <Application ID>,
$cred).GetAwaiter().GetResult().AccessToken

PowerShell example with prompt:

$ctx =
[Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new("https://login.windows.net/$ten
antName")
$redirectUri = New-Object -TypeName System.Uri -ArgumentList <Redirect URL>
$platformParameters = New-Object -TypeName
Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters -ArgumentList
([Microsoft.IdentityModel.Clients.ActiveDirectory.PromptBehavior]::Always)
$token = $ctx.AcquireTokenAsync("https://api.businesscentral.dynamics.com", <Application ID>,
$redirectUri, $platformParameters).GetAwaiter().GetResult().AccessToken

Error Format
If an error occurs during the execution of an API method, it will respond back with an error object. While the
specifics of any error will vary from endpoint to endpoint and by the error, the error object returned should
adhere to the following structure. When an error occurs that doesn't fit this structure, it typically indicates that
an error occurred in sending the request or during authentication of the request. For example, it could be that
the API hasn't yet received the request.
Error Response Object:

{
"code": string, // A stable error code describing the type an nature of the error. Ex: EnvironmentNotFound
"message": string, // A message with a readable description of the error and cause. Intended to assist with
debugging or troubleshooting the API, it's not intended to be displayed.
("target": string), // Optional - Provides information about what part of a request caused the error. Ex:
The name of a property on the request body.
("extensionData": {...}), // Optional - A key/value dictionary object containing additional information
about the error.
("clientError": [ // Optional - A nested list of error objects containing more details about the error
encountered. For instance, this may be used if multiple errors are encountered to list them all out.
{
"code": string,
"message": string,
"target": string,
"extensionData": {...},
"clientError": [...]
})
]
}

General unhandled errors


All unknown and unhandled errors that aren't covered by the lists above will use the error code: Unknown
See Also
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
App Management
2/6/2023 • 11 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1

Manage the apps that are installed on the environment.

Important Information before you get started


End-User License Agreement and Terms of Use for Installing an App
When you install an app from AppSource, you're shown a page for accepting the end-user license agreement,
terms of use, and privacy policy. This isn't the case when you install an app using the API, because there's
currently no user-interface with the feature. Instead, to install an app using the API, you must set the
"acceptIsvEula": property in the request body, which is used for agreeing to the same terms as would when
you install from AppSource. For more information, see acceptIsvEula.
Required In-Product Permissions for Installing and Uninstalling Apps
To use the install and uninstall endpoints, you must have the following permission sets assigned to your
Business Central user account or authorized Azure AAD App:

B USIN ESS C EN T RA L VERSIO N P ERM ISSIO N SET

version 18 and later Exten. Mgt. - Admin

version 17 and earlier "D365 EXTENSION MGT" or "Exten. Mgt. - Admin"

NOTE
These permissions sets are the same permission sets that allow you to use Extension Management page in tenant.
Other App management endpoints, like update or availableupdates , don't require these permission sets.

Install an App
INTRODUCED IN: API version 2.6
Installs an app on an environment.

Content-Type: application/json
POST /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/apps/{appId}/install

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment.
appId - ID of the targeted app.
Body
{
"targetVersion": "1.2.3.4", // Optional. If not provided, latest version will be installed. Required if
"allowPreviewVersion": true
"useEnvironmentUpdateWindow": false/true, // If true, the operation will be executed only in the
environment update window. It will appear as "scheduled" before it runs in the window.
"allowPreviewVersion": false/true, // If "allowPreviewVersion": true, targetVersion is required
"installOrUpdateNeededDependencies": false/true, // Value indicating whether any other app dependencies
should be installed or updated; otherwise, information about missing app dependencies will be returned as
error details
"acceptIsvEula": false/true, // Must be true for installation to proceed. Setting this to true means you
agree to the terms described in the acceptIsvEula section that follows.
"languageId": "en-US" // Optional. Specifies locale ID language code, for example, "en-US". This setting
corresponds to what the user can set in Extension Management page in tenant.Full list of values can be found
in /openspecs/office_standards/ms-oe376/6c085406-a698-4e12-9d4d-c3b0ee3dbc4a under BCP 47 Code column
}

acceptIsvEula

IMPORTANT
By setting the acceptIsvEula property to true , you not only agree with ISV's end-user license terms (EULA) but also
with these terms:
I give Microsoft permission to use or share my account information so that the provider or Microsoft can
contact me regarding this product and related products and Microsoft may share contact, usage, and
transactional information for suppor t, billing, and other transactional activities. I agree to the provider's
terms of use and privacy policy 2 and understand that the rights to use this product do not come from
Microsoft, unless Microsoft is the provider. Use of AppSource is governed by separate terms and privacy .

2 You should be able to find the terms of use and privacy policy from
the app's download page on AppSource.
Links to these documents are typically under Details + Suppor t > Legal . Or, if you can't find this information,
contact the provider.
Response
Example 200 OK response with body:

{
"id": "35601559-224a-47d5-8089-86ac88b2b995", // ID of the operation used for tracking the update request
"type": "install", // Type of the operation, for this endpoint, it's "install"
"sourceAppVersion": "", // Current version of app on the tenant. In case of Install, it is always empty as
no version is installed
"targetAppVersion": "1.2.3.4", // Version of app that will be installed.
"status": "scheduled", // An enum that indicates the status. Values include: "scheduled", "running",
"succeeded", "failed", "canceled", "skipped"
"createdOn": "2021-03-22T15:44:57.9067589Z", // Date and time the request was created
"errorMessage": "" // Error message for failed operations
}

Example 400 Bad Request response when dependent apps need to be installed first:
{
"code": "EntityValidationFailed", // Error code
"message": "Error details", // Detailed error message
"data": { // Any additional data for the error. For example, when "installOrUpdateNeededDependencies" in
the request body was set to false, and there are dependencies that must be first installed or updated.
"requirements": [ // List of requirements you need to fulfil before you can run the request
{
"appId": "1ed76016-b288-401c-92e1-75b2d47ff223",
"name": "Contoso App",
"publisher": "Contoso",
"version": "16.0.32.0",
"type": "install" // enum | "install", "update", "uninstall")
}
]
}
}

Uninstall an App
INTRODUCED IN: API version 2.6
Uninstalls an app from an environment.

Content-Type: application/json
POST /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/apps/{appId}/uninstall

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment.
appId - ID of the targeted app.
Body

{
"useEnvironmentUpdateWindow": false/true, // If set to true, the operation will be executed only in the
environment update window. It will appear as "scheduled" before it runs in the window.
"uninstallDependents": false/true // Value indicating whether any other dependent apps should be
uninstalled, otherwise information about dependent apps will be returned in error details
"deleteData": false/true // Deletes data and syncs clean the extension. Exactly the same as deleting data
in Extension Management page in tenant.
}

Response
Example 200 OK response with body:

{
"id": "35601559-224a-47d5-8089-86ac88b2b995", // ID of the operation used for tracking the update request
"type": "uninstall", // Type of the operation. For this endpoint, it's "uninstall".
"sourceAppVersion": "1.2.3.4", // Current version of app on the tenant.
"targetAppVersion": "", // Target version of the app on the tenant. For uninstall, it will be always
empty.
"status": "scheduled", // An enum that indicates the status. Values include: "scheduled", "running",
"succeeded", "failed", "canceled", "skipped"
"createdOn": "2021-03-22T15:44:57.9067589Z", // Date and time the request was created
"errorMessage": "" // Error message for failed operations
}
Example 400 Bad Request response when dependent apps need to be uninstalled first:

{
"code": "EntityValidationFailed", // Error Code
"message": "Error details", // Detailed error message
"data": { // Any additional data for the error. For example, when "uninstallDependents" in the request
body was set to false, and there are existing dependent apps that need to be uninstalled first. The list of
requirements is all apps that depend on app 35601559-224a-47d5-8089-86ac88b2b995.
"requirements": [ // List of requirements you need to fulfil before you can run the request
{
"appId": "1ed76016-b288-401c-92e1-75b2d47ff223",
"name": "Contoso App",
"publisher": "Contoso",
"version": "16.0.32.0",
"type": "uninstall" // (enum | "install", "update", "uninstall")
}
]
}
}

Get Installed Apps


Get information about apps that are installed on the environment.

GET /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/apps

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment.
Response
Returns information about the apps installed on the environment.

{
"value":
[
{
"id": Guid, // Id of the installed app
"name": string, // Name of the installed app
"publisher": string, // Publisher of the installed app
"version": string, // Version of the installed app
"state": string, // (enum | "Installed", "UpdatePending", "Updating")
"lastOperationId": Guid, // Id of the last update operation that was performed for this app
"lastUpdateAttemptResult": string // (enum | "Failed", "Succeeded", "Canceled", "Skipped")
}
]
}

Get Available App Updates


Get information about new app versions that are available for apps currently installed on the environment.

GET /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/apps/availableUpdates

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment.
Response

{
"value":
[
{
"id": Guid, // Id of the app
"name": string, // Name of the app
"publisher": string, // Publisher of the app
"version": string, // New version available of the app
"requirements": // List of other apps that need to be installed or updated before this app can be
updated
[
{
"id": Guid, // Id of the app
"name": string, // Name of the app
"publisher": string, // Publisher of the app
"version": string, // Version the required app needs to be updated to or installed
"type": string // (enum | "Install", "Update")
}
]
}
]
}

Update an App
Updates an app using an existing endpoint, but when new parameters in the request body are available.

Content-Type: application/json
POST /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/apps/{appId}/update

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment.
appId - ID of the targeted app.
Body

{
"useEnvironmentUpdateWindow": false/true, // If set to true, the operation will be executed only in the
environment update window. It will appear as "scheduled" before it runs in the window.
"targetVersion": "1.2.3.4", // Always required. There's no option to update to the latest. You have to
first do a "availableAppUpdates", call then use the version here.
"allowPreviewVersion": false/true,
"installOrUpdateNeededDependencies": false/true, // Value indicating whether any other app dependencies
should be installed or updated; otherwise, information about missing app dependencies will be returned as
error details
}

Responses (app operation)


200 OK, with Body, example:
{
"id": "35601559-224a-47d5-8089-86ac88b2b995", // ID of the operation used for tracking the update request
"type": "update", // Type of the operation. For this endpoint, it's "update".
"sourceAppVersion": "1.2.3.0", // Current version of app on the tenant.
"targetAppVersion": "1.2.3.4", // Target version of the app on the tenant that will be installed during
update.
"status": "scheduled", // An enum that indicates the status. Values include: "scheduled", "running",
"succeeded", "failed", "canceled", "skipped"
"createdOn": "2021-03-22T15:44:57.9067589Z", // Date and time the request was created
"errorMessage": "" // Error message for failed operations
}

Example 400 Bad Request response when dependent apps need to be updated first:

{
"code": "EntityValidationFailed", // Error Code
"message": "Error details", // Detailed error message
"data": { // Any additional data for the error. For example, when when "installOrUpdateNeededDependencies"
in the request body was set to false, and dependencies need to be installed or updated.
"requirements": [ // List of requirements you need to fulfil before you can run the request
{
"appId": "1ed76016-b288-401c-92e1-75b2d47ff223",
"name": "Contoso App",
"publisher": "Contoso",
"version": "16.0.32.0",
"type": "install" // (enum | "install", "update", "uninstall")
}
]
}
}

Get App Operations


Gets information about app install, uninstall, and update operations for the specified app.

GET
/admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/apps/{appId}/operations/[{opera
tionId}]

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment.
appId - Id of the targeted app.
operationId - Id of the app update operation. Used for getting information about a specific operation.
Response
Returns the list of app update operations for the specified app. Note: operationId is provided, the single
operation is returned instead.
{
"value":
[
{
"id": Guid, // Id of the operation
"createdOn": string, // Date and time the request was created
"startedOn": string, // Date and time the installation process started
"completedOn": string, // Date and time the installation process completed
"status": string, // (enum | "Scheduled", "Running", "Succeeded", "Failed", "Canceled", "Skipped")
"sourceVersion": string, // Version of the app that was installed before the installation process
started
"targetVersion": string, // Version the installed app will be updated to
"type": string, // The type of app operation
"errorMessage": string // The error message provided when update installation fails
}
]
}

Create alerts using Azure Logic Apps and Power Automate


Azure Logic Apps and Power Automate have built-in connectors that can be used to query the admin center API
by using HTTP and service-to-service (S2S) authentication. Use this capability to set up custom notifications or
to automate certain actions.

NOTE
Samples of custom notifications and automations are shared by Microsoft and third parties in the Business Central
BCTech repository on GitHub. You can also share your Application Insights alerts and automations with the community
on GitHub.

The sample below can help getting started with alerting in Microsoft Teams when app updates are available for
an environment. When updates are available, an adaptive card will be created in a Teams channel, which allows
for the automation of app updates by using S2S authentication that targets the admin center API.
Example - Run a recurrent alerting API query that sends a Teams notification when app updates are available
This Logic App runs a specified number of times a day (parameter in deployment pipeline) and lists all app
updates made available for selected environment (parameter in deployment pipeline).

Prerequisites
Business Central admin center API is configured for S2S authentication of Azure active Directory (Azure AD)
apps. For more information, go to Authenticate using service-to-service AAD Apps.
Preparation
You'll need the following information about Business Central and your Teams service to deploy the Logic App:

SERVIC E IN F O RM AT IO N

Business Central The Azure Active Directory (AD) tenant ID for


Business Central
The application (client) ID of the registered
application in Azure used for S2S authentication
The client secret of the registered application in Azure
used for S2S authentication
SERVIC E IN F O RM AT IO N

Teams The group ID of the team in Teams that you want to


send the alerts to
The ID of the channel in Teams that you want to send
the alerts to

IMPORTANT
Deploying a Logic App to Azure also creates the API connection resources necessary to authenticate certain actions in the
Logic Apps. In this example, the deployment will create a connection resource for the Teams API.
If you already have an API connection resource for Teams in your resource group, you can reuse the existing connection
resource by providing its name during deployment.

Deploy the Logic App


1. Select the Deploy to Azure button above and sign in to Azure portal when prompted.
2. Fill in the required fields on the Custom deployment page.
In the Teams Connection Name field, specify a name for the new connection resource to be added for
the Teams API. If you want to reuse the existing connection resource for the Teams API, entering the name
of the existing connection resource.
3. Select Review + create to complete the deployment.
4. When deployment is done, authorize the connection to Teams API using your Teams credentials:
a. Select Go to resource group .
b. Select the resource for the Teams API connection to open it.
c. Select Edit API connection > Authorize , then sign in with your credentials.

See Also
The Business Central Administration Center API
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
Authorized Azure AD Apps
2/6/2023 • 2 minutes to read • Edit Online

Authorized Apps are Azure Active Directory Apps authorized to call the Business Central administration center
API.

Get Authorized Azure AD Apps


Returns the Azure AD apps that are authorized to call the Business Central administration center API for the
specified Azure AD Tenant.

GET /admin/v2.15/authorizedAadApps

Response

[
{
"appId": "00000000-0000-0000-000000000000",
"isAdminConsentGranted": false
},
{
"appId": "11111111-1111-1111-111111111111",
"isAdminConsentGranted": true
}
]

Authorize Azure AD App


Authorizes an Azure AD app to call the Business Central administration center API for the specified Azure AD
Tenant. This does not grant admin consent or assign permission sets in environments to the Azure AD app.

PUT /admin/v2.15/authorizedAadApps/<appClientId>

Response

{
"appId": "00000000-0000-0000-000000000000",
"isAdminConsentGranted": false
}

Remove Azure AD App


Removes an Azure AD app authorized to call the Business Central administration center API for the specified
Azure AD Tenant. This does not revoke admin consent in Azure AD nor remove permission sets assigned to the
Azure AD app in environments.

DELETE /admin/v2.15/authorizedAadApps/<appClientId>
See Also
The Business Central Administration Center API
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
Available Applications
2/6/2023 • 2 minutes to read • Edit Online

Get information about the currently available application families, countries, rings, and versions that
environments can be created on. The API endpoints here should be utilized to determine what values can be
used for environment creation or copying

Applications and corresponding Countries with Rings


Get a list of the currently available application families, the available countries within those families, and the
available rings within the countries.

GET /admin/v2.15/applications/

Response

{
"value": [
{
"applicationFamily": string, // The name of the family for a given Business Central offered
application. (Typically this will just be "BusinessCentral")
"countriesringDetails": {
"countryCode": string, // Code for a country that the application family supports creating
environments within.
"rings": [{ // A list of logical ring groupings where environments can be created
"name": string, // The API name of the ring (for example, PROD, PREVIEW)
"productionRing": bool, // Indicates that the ring is a production ring. Currently there should
only be one production ring within a country.
"friendlyName": string, // The display friendly name of the ring
}]
}
}
]
}

Ring details with Versions


Gets a list of the currently available Versions that an environment can be created on within a logical ring group.

GET /admin/v2.15/applications/{applicationFamily}/Countries/{countryCode}/Rings/{ringName}

Route Parameters
applicationFamily - Family of the ring's application (for example, "BusinessCentral")
countryCode - Code for the ring's country.
ringName - Name of the ring to inspect.
Response
{
"value": [ // A list of the available application versions within the ring that environments can be
created on
"<version string>",
"<version string>",
...
]
}

See Also
The Business Central Administration Center API
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
Environments
2/6/2023 • 18 minutes to read • Edit Online

Environments are the instances of the application that have been set up for the tenant. An instance can be of
either a production type or a sandbox type. The environment APIs can be used to:
Get information about the environments currently set up for the tenant
Get information about the used storage and allowed quotas
Create a new environment using sample data or as a sandbox copy of the production environment
Delete an environment.

NOTE
Special care should be taken when deleting a production environment as the data will not be recoverable

Get environments and Get environments by application family


Returns a list of all the environments for the tenant.

GET /admin/v2.15/applications/environments

Returns a list of the environments for the specified application family.

GET /admin/v2.15/applications/{applicationFamily}/environments

Route Parameters
applicationFamily - Family of the environment's application as is. (for example, "BusinessCentral)
Response
Returns a wrapped array of environments.
{
"value":
[
{
"friendlyName": string, // Display name of the environment
"type": string, // Environment type (for example, "Sandbox", "Production")
"name": string, // Environment name, unique within an application family
"countryCode": string, // Country/Region that the environment is deployed in
"applicationFamily": string, // Family of the environment (for example, "BusinessCentral")
"aadTenantId": Guid, // Id of the Azure Active Directory tenant that owns the environment
"applicationVersion": string, // The version of the environment's application
"status": string, // (enum | "NotReady", "Removing", "Preparing", "Active")
"webClientLoginUrl": string, // Url to use to log into the environment,
"webServiceUrl": string, // Url to use to access the environment's service API
"locationName": string, // The Azure location where the environment's data is stored
"platformVersion": string, // The version of the environment's Business Central platform
"ringName": string, // Name of the environment's logical ring group (such as Prod, Preview)
"appInsightsKey": string // The environment's key for Azure Application Insights
}
]
}

Expected Error Codes


applicationTypeDoesNotExist - the provided value for the application family wasn't found

Get environment by application family and name


Returns the properties for the provided environment name if it exists.

GET /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Response
Returns a single environment if exists.

{
"friendlyName": string, // Display name of the environment
"type": string, // Environment type (for example, "Sandbox", "Production")
"name": string, // Environment name, unique within an application family
"countryCode": string, // Country/Region that the environment is deployed in
"applicationFamily": string, // Family of the environment (for example, "BusinessCentral")
"aadTenantId": Guid, // Id of the Azure Active Directory tenant that owns the environment
"applicationVersion": string, // The version of the environment's application
"status": string, // (enum | "NotReady", "Removing", "Preparing", "Active")
"webClientLoginUrl": string, // Url to use to log into the environment,
"webServiceUrl": string, // Url to use to access the environment's service API
"locationName": string, // The Azure location where the environment's data is stored
"platformVersion": string, // The version of the environment's Business Central platform
"ringName": string, // Name of the environment's logical ring group (such as Prod, Preview)
"appInsightsKey": string // The environment's key for Azure Application Insights
}

Expected Error Codes


environmentNotFound - the targeted environment couldn't be found
target: {applicationFamily}/{environmentName}

Create new environment


Creates a new environment with sample data.

Content-Type: application/json
PUT /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}

Route Parameters
applicationFamily - Family to create the new environment within (for example, "BusinessCentral")
environmentName - The name of the new environment. See the section below about valid environment names to
see what values are allowed.

NOTE
The Create, Copy, and Delete operations are asynchronous.
With API v2.8 and earlier, the response objects are returned before the underlying operation has completed. The final
results of the operation are reflected in the status field of the environment that the operations affect. In practice this
means that polling of the Get Environments endpoints must be done to determine if the given operation was successful.
With API v2.9 and later, consumers should rely on the status field of the corresponding EnvironmentOperation
response to monitor the status of the underlying operation. So, to get the updated status of the operation, consumers
should poll the Get environment operations for all environments endpoint rather than Get Environments and
inspect the status of the relevant operation.

Body

{
"environmentType": string, // The type of environment to create (enum | "Production", "Sandbox")
"countryCode": string, // The country to create the environment within
("ringName": string), // Optional - The logical ring group to create the environment within. Currently
only Sandbox type environments may be created in a 'Preview' ring. If not provided then the production ring
will be used.
("applicationVersion": Version), // Optional - The version of the application the environment should be
created on. If not provided then the latest available version will be used.
}

NOTE
The values for the countryCode , ringName , and applicationVersion properties should be derived from the API
endpoints described in the Available Applications section below.

Response
API v2.9 and later
EnvironmentOperation response with HTTP status code 202 (Accepted) with the following format:
{
"id": "11111111-aaaa-2222-bbbb-333333333333",
"type": "create",
"status": "scheduled", // Will eventually switch to running and then one between succeeded/failed
"aadTenantId": "",
"createdOn": "2021-09-27T08:13:46.65Z",
"startedOn": "2021-09-27T08:13:47.3Z",
"completedOn": "2021-09-27T08:15:02.073Z",
"createdBy": "",
"errorMessage": "",
"parameters": {
"sourceEnvironmentName": "",
"sourceEnvironmentType": "",
"destinationEnvironmentName": "NewEnvironment",
"destinationEnvironmentType": "Production",
"applicationVersion": "19.0.28719.0",
"countryCode": "US"
},
"environmentName": "NewEnvironment",
"environmentType": "Production",
"productFamily": "BusinessCentral"
}

API v2.8 and earlier


Returns HTTP status code 201 (Created) with newly created environment.

{
"friendlyName": string, // Display name of the environment
"type": string, // Environment type (for example, "Sandbox", "Production")
"name": string, // Environment name, unique within an application family
"countryCode": string, // Country/Region that the environment is deployed in
"applicationFamily": string, // Family of the environment (for example, "BusinessCentral")
"aadTenantId": Guid, // Id of the Azure Active Directory tenant that owns the environment
"applicationVersion": string, // The version of the environment's application
"status": string, // (enum | "NotReady", "Removing", "Preparing", "Active")
"webClientLoginUrl": string, // Url to use to log into the environment,
"webServiceUrl": string, // Url to use to access the environment's service API
"locationName": string, // The Azure location where the environment's data is stored
"platformVersion": string, // The version of the environment's Business Central platform
"ringName": string, // Name of the environment's logical ring group (such as Prod, Preview)
"appInsightsKey": string // The environment's key for Azure Application Insights
}

Expected Error Codes


DoesNotExist - the provided value for the application family wasn't found

destinationApplicationServiceNotFound - a suitable destination service couldn't be found to put the


environment. Occurs if missing or if the tenant doesn't have access to the target application.
invalidInput - the targeted property is invalid in some way
target: {countryCode} - the country code property can't be null or whitespace
target: {environmentName} - the environment name property can't be null or whitespace
target: {environmentType} - the environment type property can't be null or whitespace, and must be a
valid value (Production or Sandbox)
target: {ringName} - attempt to create a production environment on a non-production ring
target: {applicationVersion} - the version property must be a valid version string
(major.minor.build.revision)
requestBodyRequired - the request body must be provided
resourceDoesNotExist - the targeted property doesn't exist
target: {ringName} - a ring with the provided name wasn't found
resourceExists an environment with the same name already exists
environmentNameNotValid - the environment name can't be a reserved value, must be fewer than 30 characters,
must start with an alpha character and consist only of alpha, numerical, underscore (_), or dash (-) characters
cannotCreateNamedEnvironment - environments with names other than 'Production' or 'Sandbox' aren't supported
on the targeted version.
tenantAlreadyProvisioning - can't create a new environment because another environment is currently in the
process of being created.
applicationFamilyNotAccessible - the calling tenant doesn't have access to the targeted application family and
country code
environmentReservationFailed - another environment within the same application family already has this name
maximumNumberOfEnvironmentsAllowedReached - the limit on the number of allowed environments of the provided
type has been reached
maximumStorageCapacityUsageReached - the limit of the storage capacity usage has been reached

Copy environment
Creates a new environment with a copy of another environment's data.

Content-Type: application/json
POST /admin/v2.15/applications/{applicationFamily}/environments/{sourceEnvironmentName}/copy

API v2.8 and earlier:

Content-Type: application/json
POST /admin/v2.15/applications/{applicationFamily}/environments/{sourceEnvironmentName}

Route Parameters
applicationFamily - Family of the source environment's application (for example, "BusinessCentral")
sourceEnvironmentName - Name of the environment to copy from.
NOTE
The Create, Copy, and Delete operations are asynchronous.
With API v2.8 and earlier, the response objects are returned before the underlying operation has completed. The final
results of the operation are reflected in the status field of the environment that the operations affect. In practice this
means that polling of the Get Environments endpoints must be done to determine if the given operation was successful.
With API v2.9 and later, consumers should rely on the status field of the corresponding EnvironmentOperation
response to monitor the status of the underlying operation. So, to get the updated status of the operation, consumers
should poll the Get environment operations for all environments endpoint rather than Get Environments and
inspect the status of the relevant operation.

Body

{
"environmentName": string, // The name of the new environment.
"type": string // The type of environment to create. With API v2.8 and earlier, only the value "Sandbox"
is supported.
}

Response
API v2.9 and later
EnvironmentOperation response with HTTP status code 202 (Accepted) with the following format:

{
"id": "11111111-aaaa-2222-bbbb-333333333333",
"type": "copy",
"status": "scheduled", // Will eventually switch to running and then one between succeeded/failed
"aadTenantId": "",
"createdOn": "2021-09-27T08:13:46.65Z",
"startedOn": "2021-09-27T08:13:47.3Z",
"completedOn": "2021-09-27T08:15:02.073Z",
"createdBy": "",
"errorMessage": "",
"parameters": {
"sourceEnvironmentName": "SourceEnvironment",
"sourceEnvironmentType": "Production",
"destinationEnvironmentName": "NewEnvironment",
"destinationEnvironmentType": "Sandbox",
"applicationVersion": "19.0.28719.0",
"countryCode": "US"
},
"environmentName": "NewEnvironment",
"environmentType": "sandbox",
"productFamily": "BusinessCentral"
}

API v2.8 and earlier


Returns HTTP status code 201 (Created) with newly copied environment.
{
"friendlyName": string, // Display name of the environment
"type": string, // Environment type (for example, "Sandbox", "Production")
"name": string, // Environment name, unique within an application family
"countryCode": string, // Country/Region that the environment is deployed in
"applicationFamily": string, // Family of the environment (for example, "BusinessCentral")
"aadTenantId": Guid, // Id of the Azure Active Directory tenant that owns the environment
"applicationVersion": string, // The version of the environment's application
"status": string, // (enum | "NotReady", "Removing", "Preparing", "Active")
"webClientLoginUrl": string, // Url to use to log into the environment,
"webServiceUrl": string, // Url to use to access the environment's service API
"locationName": string, // The Azure location where the environment's data is stored
"platformVersion": string, // The version of the environment's Business Central platform
"ringName": string, // Name of the environment's logical ring group (such as Prod, Preview)
"appInsightsKey": string // The environment's key for Azure Application Insights
}

Expected Error Codes


applicationTypeDoesNotExist - the provided value for the application family wasn't found
destinationApplicationServiceNotFound - a suitable destination service couldn't be found to put the
environment. Occurs if missing or if tenant doesn't have access rights to the target application.
environmentNotFound - the targeted environment couldn't be found
target: {applicationFamily}/{sourceEnvironmentName}```
invalidInput - the targeted property is invalid in some way
target: {environmentName} - the environment name property can't be null or whitespace```
target: {type} - the type property can't be null or whitespace, and must be a valid value (Currently only
Sandbox)```
requestBodyRequired - the request body must be provided
resourceExists an environment with the same name already exists
environmentNameNotValid - the environment name can't be a reserved value, must be fewer than 30 characters,
must start with an alpha character and consist only of alpha, numerical, underscore (_), or dash (-) characters
cannotCreateNamedEnvironment - environments with names other than 'Production' or 'Sandbox' aren't supported
on the targeted version.
tenantAlreadyProvisioning - can't create a copy of an environment because another environment is currently in
the process of being created.
conflictingDeveloperExtensions - The source environment contains 'uploaded' extensions that are already
published to the destination service as 'developer' extensions. This condition will cause conflicts.
extensionData:
{
"conflictingExtensions": [{
"appId": guid, // The id of the conflicting extension
"name": string, // The name of the conflicting extension
"publisher": string, // The name of the person or group who published the conflicting extension
"version": string, // The version of the conflicting extension
"developerEnvironmentName": string // The name of the environment if the conflicting extension
exists in another environment owned by the tenant requesting the copy operation
}],
"sameAadTenant": bool, // Indicates if the conflicts occur on an environment that is owned by the same
tenant that is requesting the copy operation
}

environmentReservationFailed - another environment within the same application family already has the same
name
maximumNumberOfEnvironmentsAllowedReached - the limit on the number of allowed environments of the provided
type has been reached
maximumStorageCapacityUsageReached - the limit of the storage capacity usage has been reached

Delete environment
Deletes the specified environment. Warning: A production environment shouldn't be deleted.

DELETE /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}

Route Parameters
applicationFamily - Family of the environment's application. (for example "BusinessCentral")
environmentName - Name of the environment to delete.

NOTE
The Create, Copy, and Delete operations are asynchronous.
With API v2.8 and earlier, the response objects are returned before the underlying operation has completed. The final
results of the operation are reflected in the status field of the environment that the operations affect. In practice this
means that polling of the Get Environments endpoints must be done to determine if the given operation was successful.
With API v2.9 and later, consumers should rely on the status field of the corresponding EnvironmentOperation
response to monitor the status of the underlying operation. So, to get the updated status of the operation, consumers
should poll the Get environment operations for all environments endpoint rather than Get Environments and
inspect the status of the relevant operation.

Response
API v2.9 and later
EnvironmentOperation response with HTTP status code 202 (Accepted) with the following format:
{
"id": "8924140b-0da8-4bbb-8a4f-dac047944e72",
"type": "delete",
"status": "scheduled", // Will eventually switch to running and then one between succeeded/failed
"aadTenantId": "",
"createdOn": "2021-09-27T08:13:46.65Z",
"startedOn": "2021-09-27T08:13:47.3Z",
"completedOn": "2021-09-27T08:15:02.073Z",
"createdBy": "",
"errorMessage": "",
"parameters": {
"environmentName": "EnvironmentToDelete",
"environmentType": "sandbox",
"productFamily": "BusinessCentral",
"countryCode": "US",
"applicationVersion": "19.0.28719.0"
},
"environmentName": " EnvironmentToDelete",
"environmentType": "sandbox",
"productFamily": "BusinessCentral"
}

API v2.8 and earlier


Returns empty HTTP status code 202 (Accepted).
Expected Error Codes
invalidStatusCannotDeleteTenant - can't delete the environment in its current state
tenantDeletionInProgress - environment is already in the process of being deleted
ambiguousRequest - multiple environments with the same name were found
environmentNotFound - the targeted environment couldn't be found
target: {applicationFamily}/{environmentName}

Rename environment
INTRODUCED IN: API version 2.3
Schedules a rename operation on an environment.

Content-Type: application/json
POST /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/rename

Routing parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral").

environmentName - Name of the environment to rename.


Body

{
"NewEnvironmentName":"sandbox"
}

Response
202 Accepted with body. Follows the general "Operations" format, but with specific operation parameters
{
"id":"11111111-aaaa-2222-bbbb-333333333333",
"type":"environmentRename", // Operation type
"status":"scheduled",
"aadTenantId":"44444444-aaaa-5555-bbbb-666666666666",
"createdOn":"2021-04-22T12:29:06.668254Z",
"createdBy":"greg.chapman@contoso.com",
"errorMessage":"",
"parameters":{ // Operation-specific parameters
"oldEnvironmentName":"prod-1", // The old name of the environment
"newEnvironmentName":"prod-2" // The new name of the environment (the target name)
}
}

Expected Error Codes


Follows the general "Error response" format with no operation-specific error codes.

Restore environment
INTRODUCED IN: API version 2.4
Schedules a restore operation an existing environment from a time in the past.

Content-Type: application/json
POST /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/restore

Routing parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral").

environmentName - Name of the environment to restore.


Body

{
"EnvironmentName":"x-restored", // Mandatory. The name of the new environment that will be created as the
result of the resore operation.
"EnvironmentType":"production", // Mandatory. The type of the new environment.
"PointInTime":"2021-04-22T20:00:00Z" // The point in time to which to restore the environment. Must be in
ISO 8601 format in UTC.
}

Response
202 Accepted with body. Follows the general "Operations" format, but with specific operation parameters.

{
"id":"11111111-aaaa-2222-bbbb-333333333333", // Operation ID
"type":"pitRestore", // Operation type
"status":"queued", // Status
"aadTenantId":"44444444-aaaa-5555-bbbb-666666666666",
"createdOn":"2021-04-23T09:41:28.8300669Z",
"createdBy":"greg.chapman@contoso.com",
"errorMessage":"",
"parameters":{ // Parameters mimic the same from the request body
"environmentName":"x-restored",
"environmentType":"Production",
"restorePointInTime":"2021-04-22T20:00:00Z"
}
}
Expected Error Codes
Follows the general "Error response" format, but with specific error codes.
Operation-specific error codes:
PitRestoreFailed - the restore operation failed

Get available restore periods


INTRODUCED IN: API version 2.4
Returns an ordered list of available restore periods.

GET applications/{applicationType}/environments/{environmentName}/availableRestorePeriods

Response
200 OK with body. Body represents an ordered list of available restore periods that are non-overlapping and
sorted in ascending order by period start date-time. If there are no available restore periods, the list will be
empty.

{
"value":[
{
"from":"2021-01-25T14:57:04.967Z",
"to":"2021-01-25T21:06:17.737Z"
},
{
"from":"2021-01-25T21:14:48Z",
"to":"2021-01-27T14:33:15.0007416Z"
}
]
}

Get used storage of an environment by application family and name


Returns used storage properties for the provided environment name if it exists.

GET /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/usedstorage

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Response
Returns used storage information of a single environment if exists.

{
"environmentType": string, // Environment type (for example, "Sandbox", "Production")
"environmentName": string, // Environment name, unique within an application family
"applicationFamily": string, // Family of the environment (for example, "BusinessCentral")
"databaseStorageInKilobytes": int // Used database storage in kilobytes
}
NOTE
If an error occurs when calculating database storage, the corresponding property will be -1.

Expected Error Codes


environmentNotFound - the targeted environment couldn't be found

target: {applicationFamily}/{environmentName}

Get used storage for all environments


Returns a list of used storage objects for all the environments.

GET /admin/v2.15/environments/usedstorage

Response
Returns a wrapped array of used storage objects.

{
"value":
[
{
"environmentType": string, // Environment type (for example, "Sandbox", "Production")
"environmentName": string, // Environment name, unique within an application family
"applicationFamily": string, // Family of the environment (for example, "BusinessCentral")
"databaseStorageInKilobytes": int // Used database storage in kilobytes
}
]
}

Get allowed quotas


Returns different types of quotas and their limits.

GET /admin/v2.15/environments/quotas

Response
Returns quotas object.

{
"environmentsCount":
{
"production": int, // Maximum allowed number of production environments
"sandbox": int // Maximum allowed number of sandbox environments
}
"storageInKilobytes":
{
"default": int, // Amount of storage allowed by default
"userLicenses": int, // Amount of storage allowed based on the number of user licenses
"additionalCapacity": int, // Amount of storage allowed based on purchased capacity add-ons
"total": int // Total amount of allowed storage
}
}
Get environment operations
INTRODUCED IN: API version 2.6
Gets the following operations that occurred on an environment.

GET /admin/v2.15/applications/{applicationType}/environments/{environmentName}/operations

Operation types
Data is returned for the following operation types:

TYPE DESC RIP T IO N M O RE IN F O RM AT IO N

Copy3 An environment was created from a Copy a Production or Sandbox


copy of another environment. Environment in the Admin Center

Copy Endpoint

Create3 A new environment was created Create Environment in Admin Center

Create Endpoint

Delete2 An environment was deleted. Delete Environment in Admin Center

Delete Endpoint

EnvironmentAppHotfix1 App was hotfixed by using the App App Management API
Management API.

EnvironmentAppUpdate1 App was updated either by the Admin Update an App in Admin Center
Center or API update endpoint.
Update Endpoint

EnvironmentAppInstall1 App was installed by using the tenant's Extension Management Page
Extension Management page or the
API install endpoint. Install Endpoint

EnvironmentAppUninstall1 App was uninstalled by using the Extension Management Page


tenant's Extension Management
page or the API uninstall endpoint. Uninstall Endpoint

EnvironmentRename Environment was renamed by using Rename an Environment


the Admin Center
Rename Endpoint

Modify5 Records the following operations: Manage updates in Admin Center


Set update window Manage access using Azure Active
Set Application Insights key Directory groups in Admin Center
Set security group Manage access with Microsoft 365
Clear security group licenses in Admin Center
Reschedule update
Set access with Microsoft 365 licenses6

MoveToAnotherAadTenant An environment was moved to Move an Environment


another Azure Active Directory
organization by using the Admin
Center
TYPE DESC RIP T IO N M O RE IN F O RM AT IO N

PitRestore Environment was restored by using Restoring an Environment


the Admin Center

Restart4 An environment was restarted. Restart Environment

Update5 Records a long-running background


operation that occurs when an
environment is updated to a newer
version.

1 These operations are only supported with API version 2.6 and later. For these operations, the data returned is
the same as for Get App Operations, but in a different format.
2 These operations are only supported with API version 2.8 and later.
3 These operations are only supported with API version 2.9 and later.
4 These operations are only supported with API version 2.10 and later.
5 These operations are only supported with API version 2.11 and later.
6 These operations are only supported with API version 2.12 and later.
Route Parameters
applicationType - Family of the environment's application (for example, "BusinessCentral")

environmentName - Name of the targeted environment


Response
Example 200 OK response:
{

"value": [
{
"id": "552d3cb2-144e-4195-9a92-1043c4f483e9", // Id of the operation used for tracking
"type": "environmentAppInstall", // Type of operation
"status": "succeeded", // Status of operation (enum | "Queued", "Scheduled", "Running", "Succeeded",
"Failed", "Canceled", "Skipped")
"aadTenantId": "5633d4a2-6d53-4254-868f-b8d70eefed7a", // AAD tenant ID for which the operation was
executed
"createdOn": "2021-03-22T15:45:46.537Z", // Date and time the request was created
"errorMessage": "", // Error message for failed operations
"parameters": { // Additional parameters for the operation, specific to every operation type
"appId": "1bb96677-5112-4566-b742-12eebbb9a058",
"targetAppVersion": "17.0.3.0",
"countryCode": "US",
"allowPreviewVersion": true,
"ignoreUpgradeWindow": true,
"acceptIsvEula": true,
"allowDependencyUpdate": true,
"environmentName": "Production",
"environmentType": "Production",
"productFamily": "BusinessCentral"
}
},
{
"id": "5fe4ac38-a523-4c1f-80db-acd2cf848c09",
"type": "environmentRename",
"status": "succeeded",
"aadTenantId": "5633d4a2-6d53-4254-868f-b8d70eefed7a",
"createdOn": "2021-03-16T18:57:36.223Z",
"startedOn": "2021-03-16T18:57:39.053Z",
"completedOn": "2021-03-16T18:57:47.867Z",
"createdBy": "",
"errorMessage": "",
"parameters": {
"oldEnvironmentName": "Production",
"newEnvironmentName": "Production-deprecated",
"environmentName": "Production",
"environmentType": "Production",
"productFamily": "BusinessCentral"
}
}
]
}

"environmentName" , "environmentType" , and "productFamily" are only included in version 2.7 and later.

Get operations on all environments


INTRODUCED IN: API version 2.7
Gets the operations that occurred on all environments.

GET /admin/v2.15/applications/{applicationType}/environments/operations

Operation types
See Operation Types.
Route Parameters
applicationType - Family of the environment's application (for example, "BusinessCentral")
Response
Example 200 OK response:

"value": [
{
"id": "552d3cb2-144e-4195-9a92-1043c4f483e9", // Id of the operation used for tracking
"type": "environmentAppInstall", // Type of operation
"status": "succeeded", // Status of operation (enum | "Queued", "Scheduled", "Running", "Succeeded",
"Failed", "Canceled", "Skipped")
"aadTenantId": "5633d4a2-6d53-4254-868f-b8d70eefed7a", // AAD tenant ID for which the operation was
executed
"createdOn": "2021-03-22T15:45:46.537Z", // Date and time the request was created
"errorMessage": "", // Error message for failed operations
"parameters": { // Additional parameters for the operation, specific to every operation type
"appId": "1bb96677-5112-4566-b742-12eebbb9a058",
"targetAppVersion": "17.0.3.0",
"countryCode": "US",
"allowPreviewVersion": true,
"ignoreUpgradeWindow": true,
"acceptIsvEula": true,
"allowDependencyUpdate": true,
"environmentName": "Sandbox",
"environmentType": "Sandbox",
"productFamily": "BusinessCentral"
}
},
{
"id": "5fe4ac38-a523-4c1f-80db-acd2cf848c09",
"type": "environmentRename",
"status": "succeeded",
"aadTenantId": "5633d4a2-6d53-4254-868f-b8d70eefed7a",
"createdOn": "2021-03-16T18:57:36.223Z",
"startedOn": "2021-03-16T18:57:39.053Z",
"completedOn": "2021-03-16T18:57:47.867Z",
"createdBy": "",
"errorMessage": "",
"parameters": {
"oldEnvironmentName": "Production",
"newEnvironmentName": "Production-deprecated",
"environmentName": "Production",
"environmentType": "Production",
"productFamily": "BusinessCentral"
}
}
]
}

See Also
The Business Central Administration Center API
Manage Apps
Managing Production and Sandbox Environments in the Admin Center
Microsoft Dynamics 365 Business Central Server Administration Tool
Environment Database Export
2/6/2023 • 3 minutes to read • Edit Online

Allows for the export of an environment's Azure database. Databases are exported to an Azure Storage account
provided by you. There is a limit to the number of exports that can be done within a month as shown by the
'metrics' endpoint below.
Required In-Product Permissions for Exporting an Environment Database
To use the exports endpoint, you must have the D365 BACKUP/RESTORE permission set assigned to your
Business Central user account or authorized AAD App.

Get Export Metrics


Gets information about the number of exports allowed per month and the amount remaining.

GET /admin/v2.15/exports/applications/{applicationFamily}/environments/{environmentName}/metrics

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Response
Returns the metrics around the current month's database exports.

{
"exportsPerMonth": int, // The total number of allowed exports of the targeted environment every month.
"exportsRemainingThisMonth": int, // The number of exports remaining for the targeted environment that can
be performed this month.
}

Expected Error Codes


environmentNotFound - the targeted environment couldn't be found

target: {applicationFamily}/{environmentName}

Start Environment Database Export


Starts the export of an environment's database to a provided Azure storage account

Content-Type: application/json
POST /admin/v2.15/exports/applications/{applicationFamily}/environments/{environmentName}

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Body
{
"storageAccountSasUri": string, // An Azure SAS uri pointing at the Azure storage account where the
database will be exported to. The uri must have (Read | Write | Create | Delete) permissions
"container": string, // The name of the container that will be created by the process to store the
exported database.
"blob": string, // The name of the blob within the container that the database will be exported to.
Databases are exported in the .bacpac format so a filename ending with the '.bacpac' suffix is typical.
}

Expected Error Codes


environmentNotFound - the targeted environment couldn't be found

target: {applicationFamily}/{environmentName}
requestBodyRequired - the request body must be provided
exportFailed - the export failed because the target environment's version was too old, it wasn't a production
environment, the requesting tenant is a trial, the calling user doesn't have permissions to export, or the quota of
allowed exports has been used up

Get Export History


Gets information about the exports that have been done within a provided time frame, for which environment,
and by which user.

POST /admin/v2.15/exports/history?start={startTime}&end={endTime}

Query parameters
startTime - datetime // The start of the export history entry time window to query endTime - datetime // The
end of the export history entry time window to query
Response
Returns a detailed list of the database exports that occurred within the provided timeframe of the start and
end query parameters

{
"applicationType": string, // Family of the environment (for example, "BusinessCentral")
"applicationVersion": string, // The version of the environment's application at the time of the export.
"blob": string, // The name of the blob that the environment's database was exported to.
"container": string, // The name of the Azure storage account container that the environment's database
was exported within.
"country": string, // The country code of the environment.
"environmentName": string, // The name of the environment that was exported.
"storageAccount": string, // The name of the Azure storage account that the environent's database was
exported to.
"time": dateTime, // The time that the environment's database was exported.
"user": string // The user who initiated the export process.
}

NOTE
All datetime values are in UTC

Case-Invariant blocked environment names


All environment types
addremotehost
admin
api
clickonce
connectivity
deployment
error
getapp
health
home
invoicing
navwinclient
notsupported
officeaddin
phone
pwa
remotesignin
reset
shellservice
signout
tablet
Production Environment Types
production
Sandbox Environment Types
sandbox

See Also
The Business Central Administration Center API Manage Apps Microsoft Dynamics 365 Business Central Server
Administration Tool
Environment Outage Reporting
2/6/2023 • 3 minutes to read • Edit Online

Enables the ability to report that an environment isn't accessible and may require attention

Get Outage Types


Gets the list of supported categories of outages

GET /admin/v2.13/support/outageTypes

Response
Returns a list with information about the supported outage types for reporting

{
"value": [
{
"outageType": string, // The identifier of the outage type.
"name": string, // A displayable name for the outage type.
"description": string, // A displayable description for the outage type.
}]
}

Expected Error Codes


cannotGetOutages - an unhandled error occurred when trying to acquire the outage types

tenantNotFound - the calling tenant information couldn't be found

Get Outage Questions


Gets the list of metadata about questions that need to be answered when reporting an environment outage

GET /admin/v2.15/support/outageTypes/{outageType}/outageQuestions

Response
Returns the list of question metadata for the provided outage type
{
"value": [
{
"sequence": int, // The order in which the question should be answered
"parentId": int, // The identifier of a toggle question whose value indicates if this question should
be shown. that is if the parent value is 'true' then this question should also be answered
"id": string, // The unique identifier of the question
"defaultValue": string, // The default value of the question if it has no value
"questionType": string, // (enum | "None", "Toggle", "TextField", "DateTime")
"questionText": string, // The question's text to display
"required": bool, // Indicates if the question must have a value
"onText": string, // Toggle type only - display text for when the question is toggled to 'true'
"offText": string, // Toggle type only - display text for when the question is toggled to 'false'
"multiline": bool // Indicates if the value is intended to contain multi-line text
}]
}

Expected Error Codes


cannotGetOutageQuestions - an unhandled error occurred when trying to acquire the outage types
tenantNotFound - the calling tenant information couldn't be found

Get Reported Outages


Gets the list of outages that have been previously reported

GET /admin/v2.15/support/reportedoutages

Response
Returns the list of outages reported across all environments for the calling tenant

{
"value": [
{
"TenantId": string, // The id of the tenant who reported the outage.
"EnvironmentId": string, // The id of the environment that was reported to have been unavailable.
"CreatedDate": dateTime, // The date that the report was created.
"State": string, // The current state of the outage report.
"MsaasTicketId": string, // The identifier of the MSaaS ticket that is associated with the outage
report.
"IcmTicketId": string, // The identifier of the IcM ticket that is associated with the outage report.
"AppVersion": string, // The version of the environment's application at the time of the outage
report.
"PlatformVersion": string, // The version of the environment's platform at the time of the outage
report.
"OutageType": string, // The category of the reported outage.
}]
}

Expected Error Codes


cannotGetReportedOutages - an unhandled error occurred when trying to acquire the reported outages
tenantNotFound - the calling tenant information couldn't be found

Report Outage
Initiates an outage report indicating that an environment isn't accessible
Content-Type: application/json
POST /admin/v2.15/support/applications/{applicationFamily}/environments/{environmentName}/reportoutage

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Body

{
"outageType": string, // The category of the outage being reported.
"outageQuestionAnswers": [{ // The collection of answers to the questions associated with the outage type.
"id": string, // The identifier of the question being answered.
"answer": string // The answered value of the question.
}],
("contact": string), // (Optional) - The name of the person whose to contact with updates on the outage
report
("email": string), // (Optional) - An email to contact with updates on the outage report
("phone": string), // (Optional) - A phone number to contact with updates on the outage report
("appVersion": string), // (Optional) - If known, the version of the targeted environment's application
("platformVersion": string) //(Optional) - If known, the version of the targeted environment's platform
}

Response
Returns information about the created outage report

{
"creationStatus": string, // The status of the request to create an outage report. (enum | "Unknown",
"Created", "UpdatedExisting", "Error")
"msaasCaseNumber": string, // The identifier of the MSaaS ticket that is associated with the outage
report.
}

Expected Error Codes


requestBodyRequired - the request body must be provided

environmentNotFound - the targeted environment couldn't be found


target: {applicationFamily}/{environmentName}
failedToReportOutage - an unhandled error occurred when trying to report the outage

See Also
The Business Central Administration Center API
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
Environment Settings
2/6/2023 • 6 minutes to read • Edit Online

Allows you to manage environment-specific settings such as the AppInsights key or the update window.

Get Update Settings


Returns the update settings for the environment.

GET /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/settings/upgrade

Route Parameters
applicationFamily - Family of the environment's application as is. (for example "BusinessCentral")
environmentName - Name of the targeted environment
Response
Returns the environment's update settings, or "null" if none exist

{
"preferredStartTime": string, // Start of environment update window in 24h format (HH:mm). Supported by
API version 2.13 and later only.
"preferredEndTime": string, // End of environment update window in 24h format (HH:mm). Supported by API
version 2.13 and later only.
"timeZoneId": string, // Windows time zone identifier. Supported by API version 2.13 and later only.
"preferredStartTimeUtc": datetime, // Start of an environment's update window, expressed as an UTC
timestamp
"preferredEndTimeUtc": datetime // End of an environment's update window, expressed as an UTC timestamp
}

NOTE
The UTC values identify the current or next immediate occurrence of the update window. For instance, when the request is
issued, if the current time is within the update window defined for the environment, then preferredStartTimeUtc will
identify an instant in the past, and preferredEndTimeUtc will identify an instant in the future. Otherwise, both the start
and end times will identify instants in the future. For a static, deterministic set of values that uniquely identify the
definition of the update window for a given environment, refer to the preferredStartTime , preferredEndTime , and
timeZoneId values.

Expected Error Codes


environmentNotFound - the targeted environment couldn't be found

target: {applicationFamily}/{environmentName}

Get Time Zones for Update Settings


INTRODUCED IN: API version 2.13
Returns a list of time zones and basic information associated with them, such as daylight saving time and the
current offset from Coordinated Universal Time (UTC). Time zone identifiers are the only allowed values for the
timeZoneId parameter of the update settings.
GET /admin/v2.15/applications/settings/timezones

Response
Returns a wrapped array of time zones.

{
"value":
[
{
"id": string, // Time zone identifier (for example, "Romance Standard Time")
"displayName": string, // Display name of the time zone (for example, "(UTC+01:00) Brussels,
Copenhagen, Madrid, Paris")
"currentUtcOffset": string, // Offset from UTC, expressed as a time span with +/-HH:mm format (for
example, "+01:00", "-09:00")
"supportsDaylightSavingTime": boolean, // Indicates whether the time zone supports daylight saving
time rules
"isCurrentlyDaylightSavingTime": boolean, // Indicates whether daylight saving time is in effect for
the given time zone, at the instant the request is issued
}
]
}

Put Update Settings


Sets the update window start and end times.

Content-Type: application/json
PUT /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/settings/upgrade

Route Parameters
applicationFamily - Family of the environment's application as is. (for example "BusinessCentral")
environmentName - Name of the targeted environment
Body
With API version 2.13 and later, there are two different parameter sets for defining the update window: the wall-
time + timezone parameter set and the UTC parameter set. Consumers can provide either parameter set, but not
both. Earlier API versions only support the UTC parameter set.
The wall-time + timezone parameter set identifies the clock time (or "real time")—expressed in 24-hour
format, like "22:00" for 10:00 PM or "07:30" for 7:30 AM—for a given time zone. The time zone ID must be a
valid Windows time zone identifier, for example, "Romance Standard Time" or "Pacific Standard Time".
The UTC parameter set identifies the start and end times in Coordinated Universal Time.

NOTE
If the UTC parameter set is used when modifying the update window settings and the country of the environment
supports multiple time zones, the time zone shown on the Environment Details page in the admin center will be reset to
the default time zone for the country, which may not always be desirable. We recommend to use the new parameter set
when consuming API v2.13 and later.

Example with wall-time + timezone parameter set (supported only by API v2.13 and later):
{

"preferredStartTime": string, // Start of environment update window,

"preferredEndTime": string, // End of environment update window

"timeZoneId": string // Windows time zone identifier

Example with UTC parameter set:

{
"preferredStartTimeUtc": datetime, // Start of environment update window
"preferredEndTimeUtc": datetime, // End of environment update window
}

Response
Returns the updated settings

{
"preferredStartTimeUtc": datetime, // Start of environment update window
"preferredEndTimeUtc": datetime, // End of environment update window
}

NOTE
The date components of the values are ignored, only the time components are used.

Expected Error Codes


environmentNotFound - the targeted environment couldn't be found

target: {applicationFamily}/{environmentName}
- invalidRange: - the targeted logical range is invalid in some way
target: "Preferred Upgrade Window" - the specified window is too small
requestBodyRequired - the request body must be provided
ScheduledUpgradeConstraintViolation - the update window conflicts with the current update date that's set for
the environment. Either the update would occur outside the allowed update date range or, if the update date is
today, the update window is in the past. Adjust the update window or change the update date.

Put AppInsights key


Sets the connection string or instrumentation key an environment uses for Azure Application Insights resource,
which you can use to gather telemetry. For information about Application Insights and the connection
string/instrumentation key, go to Enable Environment Telemetry.

IMPORTANT
This process requires a restart to the environment, which is triggered automatically when you call this API. Plan to do this
during non-working hours to avoid disruptions.
Content-Type: application/json
PUT /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/settings/appinsightskey

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Body

{
"key": string, // The Application Insights key for the environment
}

Expected Error Codes


environmentNotFound - the targeted environment couldn't be found

target: {applicationFamily}/{environmentName}
requestBodyRequired - the request body must be provided
cannotSetAppInsightsKey - the targeted environment's status isn't 'Active'

Get Security Group


INTRODUCED IN: API version 2.8
Gets the Azure AD group currently assigned to an environment.

GET
/admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/settings/securitygroupaccess

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Response
If the group exists in Azure AD graph:

{
"id": "796d9c99-80e4-479c-8544-e745ffd18150",
"displayName": "Security group 1"
}

If a previously assigned group no longer exists in Azure AD graph:

{
"id": "796d9c99-80e4-479c-8544-e745ffd18150",
"displayName": ""
}

If no group is configured for the tenant, returns 204.


Set Security Group
INTRODUCED IN: API version 2.8
Assigns an Azure AD group to an environment.

Content-Type: application/json
POST
/admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/settings/securitygroupaccess

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Body

{
"Value": GUID, // The object Id of the Azure AD group, "11111111-aaaa-2222-bbbb-222222222222"
}

Response
Returns 200 if successful, or 404 if the group doesn't exist in Azure AD.

Clear Security Group


INTRODUCED IN: API version 2.8
Clears an Azure AD group that is currently assigned to an environment.

DELETE
/admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/settings/securitygroupaccess

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment

Get access with Microsoft 365 licenses


INTRODUCED IN: API version 2.12
Returns a boolean value that indicates whether the environment allows access with Microsoft 365 licenses.
Supported on environments of version 21.1 or later. Learn more at Set Up Access with Microsoft 365 licenses.

GET
/admin/v2.12/applications/{applicationFamily}/environments/{environmentName}/settings/accesswithm365licenses

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Response
{
"enabled": true/false
}

Set access with Microsoft 365 licenses


INTRODUCED IN: API version 2.12
Specifies whether users can access the environment with Microsoft 365 licenses. Supported on environments of
version 21.1 or later. Learn more at Set Up Access with Microsoft 365 licenses.

Content-Type: application/json
POSThttps://api.businesscentral.dynamics.com/admin/v2.12/applications/{applicationFamily}/environments/{envi
ronmentName}/settings/accesswithm365licenses

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Body

{
"enabled":"true"
}

Response
Returns 200 if successful.

See Also
The Business Central Administration Center API
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
Notifications (API)
2/6/2023 • 2 minutes to read • Edit Online

Notifications are sent to the recipient email addresses set up for the tenant. For example, notifications are sent
for update availability, successful updates, update failures, and extension validations.

Get Notification Recipients


Returns a list of notification recipients.

GET /admin/v2.15/settings/notification/recipients

Response
Returns a wrapped array of recipients.

{
"value":
[
{
"id": GUID, // Unique identifier of the recipient
"email": string, // Email address of the recipient
"name": string // Full name of the recipient
}
]
}

Expected Error Codes


tenantNotFound - the calling tenant information couldn't be found

Create Notification Recipient


Create a new notification recipient.

Content-Type: application/json
PUT /admin/v2.15/settings/notification/recipients

Body

{
"email": string, // Email address of the recipient
"name": string // Full name of the recipient
}

Response
Returns the newly created recipient.
{
"id": GUID, // Unique identifier of the recipient
"email": string, // Email address of the recipient
"name": string // Full name of the recipient
}

Expected Error Codes


invalidInput - the targeted property is invalid in some way

target: {name} - the name property can't be null or whitespace


target: {email} - the email property can't be null or whitespace
requestBodyRequired - the request body must be provided
tenantNotFound - the calling tenant information couldn't be found

Delete Notification Recipient


Deletes an existing notification recipient.

DELETE /admin/v2.15/settings/notification/recipients/{id}

Route Parameters
id - The unique identifier of the notification recipient to delete.

Expected Error Codes


invalidInput - the targeted property is invalid in some way

target: {id} - provided id can't be the empty guid


tenantNotFound - the calling tenant information couldn't be found

Get Notification Settings


Returns the full set of notification settings including the list of recipients.

GET /admin/v2.15/settings/notification

Response
Returns the notification settings.

{
"aadTenantId": GUID, // AAD Tenant ID of the caller
"recipients": [
{
"id": GUID, // Unique identifier of the recipient
"email": string, // Email address of the recipient
"name": string // Full name of the recipient
}
]
}

Expected Error Codes


tenantNotFound - the calling tenant information couldn't be found
See Also
The Business Central Administration Center API
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
Reschedule Updates
2/6/2023 • 2 minutes to read • Edit Online

Allows for the management of scheduled updates such as rescheduling the update to a run on or after a specific
date within a provided range.

Get Scheduled Update


Get information about updates that have already been scheduled for a specific environment.

GET /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/upgrade

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Response
Returns information about the scheduled update for that environment.

{
"environmentName": string, // The name of the targeted environment.
"applicationFamily": string, // Family of the environment (for example, "BusinessCentral")
"sourceVersion": string, // The current version of the environment's application.
"targetVersion": string, // The version of the application that the environment will update to.
"canTenantSelectDate": boolean, // Indicates if a new update date can be selected.
"didTenantSelectDate": boolean, // Indicates if the tenant has selected the current date for the update.
"earliestSelectableUpgradeDate": datetime, // Specifies the earliest date that can be chosen for the
update.
"latestSelectableUpgradeDate": datetime, // Specifies the latest date that can be chosen for the update.
"upgradeDate": datetime, // The currently selected scheduled date of the update.
"updateStatus": string, // The current status of the environment's update. (enum | "Scheduled" or
"Running")
"ignoreUpgradeWindow": boolean, // Indicates if the environment's update window will be ignored
"isActive": boolean, // Indicates if the update is activated and is scheduled to occur.
}

Expected Error Codes


applicationTypeDoesNotExist - the provided value for the application family wasn't found
environmentNotFound - the targeted environment couldn't be found
target: {applicationFamily}/{environmentName}

Reschedule Update
Reschedule an update, if able.

Content-Type: application/json
PUT /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/upgrade

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Body

{
"runOn": datetime, // Sets the date that the upgrade should be run on.
"ignoreUpgradeWindow": boolean // Specifies if the upgrade window for the environment should be respected.
}

Expected Error Codes


applicationTypeDoesNotExist - the provided value for the application family wasn't found
requestBodyRequired - the request body must be provided
resourceDoesNotExist - no upgrade is currently scheduled for the targeted environment
entityValidationFailed - some unhandled error occurred in the validation of the request
environmentNotFound - the targeted environment couldn't be found
target: {applicationFamily}/{environmentName}

See Also
The Business Central Administration Center API
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
Session Management
2/6/2023 • 2 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1

Manage the active sessions on an environment.

Get active sessions


Gets active sessions for an environment.

GET /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/sessions

Response

{
value: [
{
environmentName: string,
applicationFamily: string,
sessionId: int,
userId: string,
clientType: string,
logOnDate: string,
entryPointOperation: string,
entryPointObjectName: string,
entryPointObjectId: string,
entryPointObjectType: string,
currentObjectName: string,
currentObjectId: int,
currentObjectType: string,
currentOperationDuration: long
}
,...
]
}

Get session details


Gets session information for a specific session id.

GET /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/sessions/{sessionId}

Response
{
environmentName: string,
applicationFamily: string,
sessionId: int,
userId: string,
clientType: string,
logOnDate: string,
entryPointOperation: string,
entryPointObjectName: string,
entryPointObjectId: string,
entryPointObjectType: string,
currentObjectName: string,
currentObjectId: int,
currentObjectType: string,
currentOperationDuration: long
}

Stop and delete a session


Terminates and deletes an active session.

DELETE /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/sessions/{sessionId}

See Also
The Business Central Administration Center API
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
Support Settings
2/6/2023 • 2 minutes to read • Edit Online

Allows for the management of support settings, such as changing the contact, for a specific environment

Get Support Contact


Get information about the support contact for a specified environment.

GET /admin/v2.15/support/applications/{applicationFamily}/environments/{environmentName}/supportcontact

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Response
Returns information about the support contact for that environment.

{
"name": string, // The name of the support contact.
"email": string, // The email address of the support contact.
"url": string, // A freeform url for additional support contact information such as a support website.
}

Expected Error Codes


applicationTypeDoesNotExist - the provided value for the application family wasn't found
environmentNotFound - the targeted environment couldn't be found
target: {applicationFamily}/{environmentName}
resourceDoesNotExist - couldn't find the necessary information to communicate with the targeted
environment's API
businessCentralCommunicationException - an unhandled error occurred when communicating with the targeted
environment's API

Set Support Contact


Sets the support contact information for a specified environment

Content-Type: application/json
PUT /admin/v2.15/support/applications/{applicationFamily}/environments/{environmentName}/supportcontact

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Body
{
"name": string, // The name of the support contact.
"email": string, // The email address of the support contact.
"url": string, // A freeform url for additional support contact information such as a support website.
}

Response
Returns the newly updated support contact information.

{
"name": string, // The name of the support contact.
"email": string, // The email address of the support contact.
"url": string // A freeform url for additional support contact information such as a support website.
}

Expected Error Codes


applicationTypeDoesNotExist - the provided value for the application family wasn't found
environmentNotFound - the targeted environment couldn't be found
target: {applicationFamily}/{environmentName}
requestBodyRequired - the request body must be provided
resourceDoesNotExist - couldn't find the necessary information to communicate with the targeted
environment's API
businessCentralCommunicationException - an unhandled error occurred when communicating with the targeted
environment's API

See Also
The Business Central Administration Center API
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
Telemetry (API)
2/6/2023 • 2 minutes to read • Edit Online

Telemetry includes the top-level AL events and any returned errors logged from the service. These events can
provide necessary information and errors that can be used to troubleshoot issues happening in the tenant's
environment.

Get Environment Telemetry


Returns the telemetry information for the provided environment and filters. it's recommended that you provide
start and end time parameters to return a manageable data set.

GET /admin/v2.15/applications/{applicationFamily}/environments/{environmentName}/telemetry?startDateUtc=
{start}&endDateUtc={end}&logCategory={cat}

Route Parameters
applicationFamily - Family of the environment's application (for example, "BusinessCentral")
environmentName - Name of the targeted environment
Query parameters
start : datetime // The start of the telemetry entry time window to query
end : datetime // The end of the telemetry entry time window to query
cat : (All or 0) // Category of telemetry to query

Response
Returns the telemetry logs and with data column headers.

{
"queryColumns": [
{
"name": string, // Column display name
"ordinal": int, // Index of the column in the data set
"dataType": ( string or 0 | numeric or 1 | datetime or 2 )
"expectations": (none or 0 | wide or 1) // Flags enum value
}
],
"queryResults": object[][] // Raw query data results
}

Expected Error Codes


applicationTypeDoesNotExist - the provided value for the application family wasn't found
environmentNotFound - the targeted environment couldn't be found
target: {applicationFamily}/{environmentName}
invalidInput - the targeted property is invalid in some way
target: {logCategory} - the provided log category isn't a valid value

See Also
The Business Central Administration Center API
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
Licensing in Dynamics 365 Business Central
2/6/2023 • 7 minutes to read • Edit Online

Business Central licenses can only be purchased through CSP. Microsoft offers several types of paid licenses for
business users:
Essential
Premium
Team Member
External Accountant
Microsoft also offers read-only access to Business Central through Microsoft 365 licenses, as an addition to
Premium or Essentials plans
Prospects and customers can also subscribe for an evaluation version by using self-service sign-up, also known
as the viral trial. This subscription comes with 10,000 licenses, and partners can use such viral trials to let
prospects explore Business Central using non-production companies. For more information, see Preparing
Demonstration Environments of Dynamics 365 Business Central.

IMPORTANT
Specifically for businesses who want to convert a 30-day trial company into their actual production company, the first
user who signs into Business Central after the license was applied to their tenant must be a user with this license
assigned. This way, the 30-day trial ends, and any trial-related notifications disappear so that users can use Business
Central to do work.
If an administrator is the first person to sign in after the license was applied to the tenant and to users, then the trial will
continue until it expires.

Business Central online doesn't use the classic Dynamics NAV license files (.flf). Instead, permissions are
generated based on entitlements.
Behind the scenes, the Entitlements table defines license permissions per object. Entitlements are grouped in
the Entitlement Set table, and then each entitlement set is associated with one of the four Azure Active
Directory (Azure AD) service plans.
This condition means that when a user purchases, for example, an Essential license and tries to sign in to
Business Central, we retrieve the user's service plan (in this case Essential) from Azure AD. Then, we load the
corresponding entitlements as license permissions.

NOTE
For more information about the different types of licenses and how licensing works in Business Central, see the Dynamics
365 Licensing Guide, which you can download from https://go.microsoft.com/fwlink/?LinkId=866544.

Entitlements and user groups


Entitlements are permissions that describe which objects in Business Central a user is entitled to use according
to their Azure Active Directory role or the license they purchased from Microsoft.
The User Group Plan table stores the mapping between the service plans and the user groups. Based on this
mapping, the service determines which user group is assigned to a user by default when a user logs in to
Business Central for the first time. The user group assigns a specific license (or makes the user a member of a
specific Azure AD role).
When a user logs in to Business Central, the service applies the intersection of the entitlements that are
associated with the user's service plan (or Azure AD role) and the permissions that are defined for that user.
Entitlements always have higher priority over permissions. For example, even is the user is given SUPER
permissions by the admin but has the Team Member license assigned – the user can still only access the objects
defined by the Team Member entitlements.
You can verify how entitlements, licenses, and user groups work together by looking at the Effective
Permissions page, which you can access from the User page. Starting with 2022 release wave 1, admins can
also customize the default permissions per license type. For more information, see Create Users According to
Licenses in the business functionality content for Business Central.
Entitlements in production and sandbox environments
In versions earlier than 2020 release wave 2 (version 17.0), entitlements are only enforced in production
environments so that prospective and existing customers could explore the functionality of the Premium
subscription in a sandbox environment without having to purchase a Premium license.
However, partners that create and test their extensions using sandbox environments of that type could miss
errors in their code that would be related to entitlements or access, so that those issues wouldn't be found until
they deployed their extensions to the production environments. But since 2020 release wave 2, the license
checks for entitlements are now also enforced in the sandbox environments.
Now, you can explore such functionality by creating an evaluation company in either a production or a sandbox
environment using the free evaluation subscription that is available from
https://dynamics.microsoft.com/business-central. Alternatively, you can use the Business Central Premium -
Trial subscription that is available through the CSP program as described here. By using these subscription
types, customers and partners can explore the capabilities included with the Premium subscription.

Reassigning licenses
The licensing terms in the Online Services Terms document don't allow temporary assignment of a license that
belongs to one user to another user.
Most, but not all, licenses can be reassigned. Except as permitted in this paragraph or in the Online Service-
specific Terms, the customer can't reassign a license on a short-term basis, meaning within 90 days of the latest
assignment. The customer can reassign a license on a short-term basis to cover a user's absence or the
unavailability of a device that is out of service. Reassignment of a license for any other purpose must be
permanent. When a customer reassigns a license from one device or user to another, they must block access and
remove any related software from the former device or from the former user's device.

Device licenses
The Dynamics 365 Business Central Device license allows multiple users to simultaneously use a device that is
covered by the license. For example, it might be a point of sales, shop floor, or warehouse device. When you've
purchased many device licenses, up to that number of users assigned to the Dynamics 365 Business Central
Device Users group can sign in at the same time. For more information, see the Microsoft Dynamics 365
Business Central Licensing Guide. The guide is available for download on the Business Central website.
Your company's Microsoft 365 administrator or Microsoft partner can create the Dynamics 365 Business Central
Device Users group and add device users as members in the Microsoft 365 Admin Center or on the Azure
portal.
Device user limitations
Users with the Device license can't perform the following tasks in Business Central:
Set up jobs to run as scheduled tasks in the job queue. Device users are concurrent users and, therefore,
we can't ensure that the involved user is present in the system when a task is executed, which is required.
A device user can't be the first user to sign in. A user of type Administrator, Full User, or External
Accountant must be the first to sign in so they can set up Business Central. For more information, see
Administration of Business Central Online.
To create the Dynamics 365 Business Central Device Users group
1. In the Microsoft 365 Admin Center, go to the Groups page.
2. Choose the Add a group action.
3. On the Choose a group type page, choose the Security option, and then choose the Add action.
4. On the Basics page, enter Dynamics 365 Business Central Device Users as the name of the group.

NOTE
The name of the group must be spelled in English exactly as shown in step 4, even if you are using another
language. If you have copied the name of the group from a document, such as a PDF, verify that the name does
not contain extra spaces.

5. Choose the Close button.

NOTE
You can also create a group of type Microsoft 365. For more information, see Compare Groups

To add members to the group


1. In the Microsoft 365 Admin Center, refresh the Groups page so your new group appears.
2. Select the Dynamics 365 Business Central Device Users group, and then choose the View all and
manage members action.
3. Choose the Add members action.
4. Select the users that you want to add, and then choose the Save button.
5. Choose the Close button three times.
You can add as many users to the Dynamics 365 Business Central Device Users group as you need. However, the
number of devices that users can simultaneously sign in to is defined by the number of purchased device
licenses.

NOTE
You do not need to assign a Business Central license to users that are members of the Dynamics 365 Business Central
Device Users group.

Microsoft 365 licenses


Microsoft 365 users can access Business Central data in Microsoft Teams, using only their Microsoft 365 license.
This capability is intended for employees across the organization to participate in team decisions and
collaboration when Business Central records are shared with them.
For a detailed overview of the use rights, minimum requirements and which Microsoft 365 plans are supported,
see Business Central Access with Microsoft 365 Licenses.

See Also
Get Started as a Reseller of Business Central Online
Deployment of Dynamics 365 Business Central
Working with Sandboxes and Entitlements
Embed App Overview
Entitlements and Permission Sets Overview
2/6/2023 • 5 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

Business Central uses two main concepts for defining access to functionality: Entitlements and permissions.
Entitlements describe which objects in Business Central a customer is entitled to use according to the
license that they purchased from Microsoft or according to the Azure Active Directory role that they have
assigned in Microsoft 365 Admin Center, such as Global Administrator. Entitlements are only used in the
online version of Business Central.
Permissions describe which objects an administrator or a partner has given the user.
Permission sets combine objects permissions in logical groups (or sets), which can then be assigned to
the users explicitly or through a user group.
For more information about assigning licenses, see Licensing in Dynamics 365 Business Central. For more
information about how to create and assign permissions, see Assign Permissions to Users and Groups.

Permission Set scope


A Business Central solution contains a number of predefined permission sets that are added by Microsoft or by
your software provider (by an ISV application that you installed from AppSource).
Permission sets included with Microsoft and AppSource apps defined as AL objects are of the type System .
End-users cannot create or edit these types of permission sets or the permissions within them. However, they
can copy these permission sets to define their own permission sets and permissions. Permission sets that users
create, from new or as copies, are of the type User-Defined and they can be edited.

Creating entitlements and permission sets in AL


When developing an app, entitlements and permission sets are handled as objects in AL, and existing
permission sets can be extended in AL. The following object types are used for handling entitlements and
permissions:
Entitlement Object
PermissionSet
PermissionSetExtension

NOTE
In the current version of Dynamics 365 Business Central entitlements can only be included with Microsoft apps (enforced
by the AppSource cop rules and the technical validation checks that we run for the apps submitted to AppSource). These
objects will become available for the ISV apps when we introduce ability to monetize AppSource apps in one of our future
releases.

Upgrade considerations
Starting with Business Central 2021 release wave 1 (v18.0), the Business Central demo database, which is
shipped with our on-premises installation, doesn't contain any data in the Permission Set and Permission
tables in the application database. Instead, the System permission sets and permissions are provided as AL
objects of type PermissionSet and PermissionSetExtension , included with Microsoft apps.
The application database tables that used to store the entitlements won't contain any data either, because
entitlements are now defined as AL objects.
Business Central server configuration file (CustomSettings.config) includes a setting that allows on-premises
administrators to decide whether they want to continue using the permissions defined as data or as AL objects:

<add key="UsePermissionSetsFromExtensions" value="true" />

The default value for this setting is true , meaning that the server will be retrieving all System permission sets
and permissions from the AL objects of type PermissionSet and PermissionSetExtension . With the value for this
setting set to true , the permissions data, in case it is still present in the application database, will be
disregarded.
It's not possible to customize the System permission sets and permissions used in the online version of
Business Central. End-users can only copy these types to new permission sets, which they can then adjust to
their needs. For more information, see Assign Permissions to Users and Group.
In the on-premises version of Business Central, even though it's not recommended, the partners can customize
the permission sets and permissions shipped in the application database. In this case, as for any upgrade before,
the changes in Microsoft permissions should be merged with the customized permissions by partners during
upgrade.
Although starting with Business Central 2021 release wave 1 (v.18.0), System permissions are no longer
shipped as data in the application database, the partners can use the same procedure as before to export the
new permissions that are defined using AL objects. The new permission sets and permissions can be exported
into XML file by running XMLport 9171 Import/Export Permission Sets, making it possible to compare and
merge the customized permission sets in your old database with the newly shipped permission sets. Find more
details, see Export and Import Permission Sets and Permissions.
How to upgrade permission sets
When upgrading to version 18, first decide whether you want to use the permissions defined as data or switch
to permissions defined as AL objects. Then, follow the guidelines at Upgrading Permission Sets for details on
how to do the upgrade.

Earlier versions of Business Central


In releases of Business Central prior to 2021 release wave 1 (v18.0), System and Extension permissions and
entitlements were defined as data in the application database:
Entitlements tables:
Entitlement
Entitlement Set
Membership Entitlement
Permissions tables:
Permission Set
Permission
Keeping such sensitive information as data comes with additional maintenance, security, and audit risks for the
software providers (ISVs). Changes applied to this data should ideally be well traceable, easy to update and
maintain. Starting with Business Central 2021 release wave 1, the System permissions and entitlements are
defined in code, using Entitlement, PermissionSet, and PermissionSetExtension AL objects. This change provides
ISVs with all of the advantages of using the AL Language extension in Visual Studio Code and source control
systems (as Visual Studio Online and GitHub) to design, get an overview, and track changes to the objects that
describe user access.
Turning this data into code has another significant advantage: the ability to apply hotfixes to the entitlements
and permissions in the same way that the hotfixes are applied to the apps themselves, simply by updating an
app to a new version which carries fixed code. This improves Business Central support agility considerably,
ultimately improving customer satisfaction with the service.
And finally, the new AL objects are envisioned to become the core building blocks in the story of monetizing the
AppSource apps. It's through these new AL objects that AppSource ISVs will be able to define which capabilities
of their apps should be made available to their users, when the customers purchase their app licenses. With
Business Central 2021 release wave 1, we're paving the way by moving the entitlements and permission sets
into AL objects for Microsoft apps, so that ISVs can follow the same approach for their apps, when the
monetization story is introduced with one of the next releases of Business Central.
User-Defined permission sets and permissions, and functionality around them, remain unchanged. They're still
stored as data in the tenant database:
Tenant Permission
Tenant Permission Set
Permission sets and permissions included with apps in XML format will continue to work as before, however, we
recommend you to start using the AL objects of type PermissionSet and PermissionSetExtension instead.

See Also
Get Started with AL
Entitlement Object
PermissionSet Object
PermissionSet Extension Object
Special Permission Sets
2/6/2023 • 2 minutes to read • Edit Online

The following permission sets have special definitions that you should be aware of as you implement
permissions and security for Business Central users.

P ERM ISSIO N SET DEF IN IT IO N

SUPER Can read, use, update, and delete all data and all application
objects in the scope of your license. Business Central
requires that at least one user is assigned this permission set
in each database.

The first user created is automatically assigned the SUPER


Permission Set

You can't modify permissions for the SUPER permission set.

SUPER (DATA) Can read, use, update, and delete all data in the scope of
your license. You typically assign this permission set to an
accounting manager who needs to work with all data but
doesn't need to change Business Central.

SECURITY Manage the permission sets that are assigned to your


account. When assigned this permission set, you can:
Create new users and assign them any permission
set that is also assigned to your account.
Remove a permission set from a user as long as the
permission set is also assigned to your account.
Modify individual permission granted by a permission
set as long as the permission set is also assigned to
your account.
The idea behind this permission set is to prohibit you from
granting users more permissions than you have. The
permission set is useful for SUPER users or global
administrators who want to delegate permission
management to team administrators. For example, a sales
manager can assign permissions in sales area to sales
people, sales assistant, sales coordinator, and so on.

BASIC Grants Read access to almost all application tables and all
system tables.

The main purpose of this permission set is to enable the


service to open and show all pages.

Note: This permission set is available only for Business


Central on-premises.

D365 BASIC Grants Read access to almost all application tables and all
system tables.

The main purpose of this permission set is to enable the


service to open and show all pages.
P ERM ISSIO N SET DEF IN IT IO N

FOUNDATION UI A prerequisite for all other permission sets. The


FOUNDATION permission set grants access to system tables
and application setup tables that are required for most
application features to work. Note: This permission set is
recommended when using the UI Elements Removal feature
to automatically remove UI elements according to user
permissions. For more information, see Removing Elements
from the User Interface According to Permissions.

Note: This permission set is available only for Business


Central on-premises.

SYSTEM APP - BASIC Grants access to most features of the system application and
is required for login to Business Central.

SYSTEM APP - ADMIN Grants full permissions to all features of the System
Application.

LOGIN Grants the minimum permissions to application and system


objects that needed to sign in to Business Central. Use the
permission set to allow users to sign in to Business Central
without accidentally granting them permissions beyond
those required by their tasks. By granting this permission
set, the user will always be able to sign in.

Note: This permission set does not grant access to a Role


Center. It only allows the user to log in to Business Central.

See Also
Removing Elements from the User Interface According to Permissions
Enabling Upcoming Features Ahead of Time
2/6/2023 • 9 minutes to read • Edit Online

New capabilities are added to Business Central in major updates and minor updates. Some new features can be
enabled ahead of time on sandbox and production environments. Learn how you as an administrator can turn
on new features using the Feature Management page.

Managing optional features


Some new features can be enabled ahead of time on sandbox and production environments. This capability
allows you to benefit as early as possible from feature improvements and innovative new features. It gives you
the time you need to test and prepare your organization for change.
When Microsoft releases features or feature design improvements as part of minor updates, some features
aren't immediately enabled. Users as well as administrators can learn about these features in the release plans,
and administrators can enable each individual feature from the Feature Management page inside Business
Central. Once a feature is enabled, it becomes available for all users on that environment no matter how they
access Business Central.
These features are only optional for a while. The option period typically starts from the minor update in which
they're made generally available. The period ends when the features become mandatory and are automatically
enabled in a later major update. To see the approximate date and service update when each feature is expected
to become mandatory, see the Automatically enabled from field in the Feature Management page. After
this date, the feature will no longer appear in the Feature Management page and can no longer be turned off.

IMPORTANT
The projected timeline for a feature is subject to change (see Microsoft policy).

Example timeline for an optional feature

Learn about what's new and planned.


Learn about new features available in the last minor update in a release wave.
TIP
To prepare for an upcoming feature, consider enabling the feature on a sandbox environment that has a copy of
production data. Invite business users to test out the change using real-world tasks. Once you and your users are
satisfied with the change, you can then enable it on production environments where they can immediately benefit from
that feature.

How to enable an optional feature


NOTE
Features might require that one or more other features are also enabled, and perhaps even first. If the feature you want
to turn on depends on other features, Business Central will let you know. The prerequisite features are indented beneath
the feature you want to turn on. Information about prerequisites is also available in the Dependent Features FactBox.

1. Sign in to your environment and navigate to the Feature Management page, or use this link:
https://businesscentral.dynamics.com/?page=2610.
2. If the page isn't editable, choose the Edit List action.
3. For the feature you want to turn on, in the Enabled for field, choose All users .
As soon as you enable the feature, any user who signs in to that environment experiences the change. You won't
necessarily experience the change yourself until you sign out and sign in again, or start a new session.

TIP
Try out the feature for yourself without enabling it for all users by choosing the Tr y it out link. This will open a new
browser tab with the feature enabled for that session. Any new sessions in your browser will also have the feature
temporarily turned on. To stop trying the feature, close your browser window or sign out.

If you manage multiple environments, such as several sandboxes, new features can be enabled in some of these
environments and not in other environments. It can be tricky to keep track of what is enabled where in such
scenarios, but the Feature Management page always shows what is enabled in a given environment.

Features that can't be turned off


Some features or feature improvements may permanently affect the state and capabilities of Business Central
and can't be safely reverted. These irreversible features can't be turned off again after they've been enabled.
Before you turn on an irreversible feature on a production environment, we recommend that you first evaluate it
in a sandbox environment that is a copy of the production environment.

NOTE
When you choose to enable an irreversible feature, a warning dialog that describes the consequences is displayed. Choose
the Yes action to turn on the feature in that environment.

Starting with version 19.1, when you create a copy of an environment, any irreversible features that were turned
on are also available in the copy.

Scheduling data updates for new features


Enabling application features that change the user experience or update data can be a disruptive process. So you
might want to go at your own pace. For example, schedule an update per company for a time that's after your
users have been trained for the new experiences.
You schedule a data update on the Feature Management page by choosing the Schedule action, or by
choosing All Users in the Enable for column. Both of those actions start the Feature Data Update setup
guide. This guide allows you to review the affected data and schedule the update process. When the data update
process is completed, the feature is enabled in the company where you ran the data update.

NOTE
For a feature that requires data update, data is created based on the data for the existing feature. The data for the
existing feature may remain available, however, it is not synchronized with data for the new feature. Therefore, we
recommend that you use one feature or the other, but not both.

Control user access to feature management


Most users, by default, won't have permission to enable upcoming features themselves. As an administrator, the
easiest way to give a user permission is to assign them the FEATURE MGT. - ADMIN permission set. For more
information, see Assigning Permission Sets. This permission set was introduced in version 18.1.

FAQ about Feature Management


Why do I have to enable another feature before I can get the feature I want?
Some features are built to work together with one or more other features. That means that a feature might need
functionality that another feature provides, so you must enable the other features first. When that's the case, the
dependent features are indented under the primary feature in the list.
There are no features listed as optional. Did I do something wrong?
There may be periods where no optional features have been made available, which is perfectly normal. There
will likely be few or no features listed in the Feature Management page immediately after a major update.
Why can't I enable features and make other changes on the Feature Management page?
Chances are you don't have permissions to this page. See Control user access to feature management or talk to
an administrator.
Will all new features eventually be listed on the Feature Management list?
No. We carefully select applicable features based on different criteria so that only a manageable subset of new
features will appear in the list. Selected features are primarily those features that change the visuals or
behaviors of the user interface and which require significant effort for business users to adjust to.
Are these features still under development or in beta/preview?
No. Features listed in the Feature Management page are considered ready and generally available. Most of these
features are automatically enabled on newly provisioned environments for new customers to benefit from.
Does Microsoft provide support for optional features?
Yes. Features that are listed in the Feature Management page are considered ready. They follow the standard
support lifecycle for the service update in which they're first made available.
Will Business Central notify me closer to the date when a feature becomes mandatory?
No. Users and administrators don't receive any in-app or email notifications about approaching dates for
features becoming automatically enabled.
Do these features show in the Microsoft 365 admin center Message center?
At this time, new Business Central features aren't listed in Message center.
How is feature management different to the Early Access program?
The Early Access program that is used by some Dynamics 365 apps makes a large set of new features available
two months before a major update. It allows customers to enable those features in production. The most
significant difference is that the Early Access program features are always two months before the major update.
How is feature management different to preview environments?
Preview environments are Business Central online sandbox environments that include all new platform and
application features that will become available with the upcoming major update. The most significant difference
is that a preview environment includes all new features bundled together. You don't have the opportunity to
select which feature to enable and test.
How is feature management different from application area tags?
Application areas are a concept where developers specify differentiated user experiences in the business
application. By using application areas, developers can show or hide individual controls on a page. Like feature
management, application areas concept also puts administrators in control of selecting the preferred experience
tier. One difference is that there's no time period during which application areas can be optionally enabled.
Another difference is that they only apply to business application controls.
Can resellers, ISVs, and developers contribute to the list of features?
No. At this time, feature management is only for features that are released by Microsoft.
Can I turn on a feature for a single user?
No. Business Central doesn't let you turn on a feature for a single user or group of users. Enabled features apply
to all users of an environment.
I don't see a link to try out an optional feature. Is something wrong?
Some features don't provide a way to try it out for yourself and won't display a Tr y it out link. Before you turn
on these features, we recommend that you first test the features in a sandbox environment that is a copy of the
production environment.
Are optional features also optional on new environments?
Yes. Most optional features are turn on by default in new environments for new customers to benefit from.
Administrators can still turn any of these features off from the Feature Management page. Some features are
irreversible and aren't turn on by default.
Starting with version 19.1, when you create a copy of an environment, any irreversible features that were turned
on are also available in the copy.
Are optional features automatically enabled on sandbox environments?
When you create a new sandbox environment with a copy of production data, your choice of enabled features is
also copied to the sandbox. When you create a fresh sandbox, each feature is enabled by default, unless a
feature is irreversible.
Why does the list include features that apply to other countries?
Microsoft's business functionality in Business Central consists of functionality that is generic and functionality
that is particular to a specific country or region. The Feature Management page will at times show optional
features that are particular to a country, even if your Business Central is based on another country-specific
version. This is due to the current limitations of feature management, which relies on a system table to populate
the Feature Management page.
In a future version, we hope to redesign feature management to better reflect local functionality and partner-
provided functionality.
Is feature management applicable to on-premises deployments of Business Central?
Yes. You can turn optional features on or off in a similar way.
See also
New and planned features
Administration of Business Central Online
Major updates of Business Central Online
Recommend Apps
2/6/2023 • 2 minutes to read • Edit Online

The Microsoft commercial marketplace offers a wide variety of apps from Microsoft and our partners that
extend the value of Business Central. As a Microsoft partner, you can save yourself, and your customers, a bit of
legwork by using the Recommended Apps extension to curate a list of apps that are right for your customers'
businesses. Recommended Apps is a per-tenant extension (PTE), which means that you can make collections
unique for each customer, or build collections specifically for certain types of businesses or industries and then
reuse the collections when you're on-boarding those types of customers. For example, you can create one
collection for customers who work in finance, and another for customers in the retail space. For more
information, see Maintain AppSource Apps and Per-Tenant Extensions in Business Central Online.

Before you begin


You can only add apps that are available on AppSource to your collection. That is, you cannot host your own app
and add it to the list.

Building a collection of recommended apps


Building collections requires some development. To make that easier, Business Central provides the following
objects:
Recommended Apps List page
Recommended App Card page
Recommended Apps table
Recommend Apps codeunit
You must use the Recommend Apps codeunit to build collections. The following table provides an overview of
the methods in the codeunit. You can copy the information for the parameters from the listing for the app on
AppSource.

M ET H O D DESC RIP T IO N

Inser tApp Add information about the apps from AppSource to the
Recommended Apps table. When adding new apps, you can
simply paste the URL for the app from AppSource for the
AppSourceUrl parameter, and Business Central will add the
relevant parts to the other parameters. However, you must
manually complete the Short Description ,
Long Description , and Recommended By parameters.

GetApp Get information from AppSource about the apps that are
already added to the Recommended Apps table.

UpdateApp Update the information about the apps that are already
added to the Recommended Apps table.

RefreshImage Update the logo for the app. When you insert an app, the
image is downloaded automatically. Use if the logo has
changed.
M ET H O D DESC RIP T IO N

DeleteApp Delete an app from the collection. You provide the app ID.

DeleteAllApps Delete all apps from the collection.

GetAppURL Get the URL for a specific app. You provide the app ID.

Providing the collection to customers


When your collection is ready, you can deploy it to customer tenants. For more information, see Deploying a
Tenant Customization. Afterward, the Recommended Apps page will display the apps and your customer can
install them. Customers can choose the app in the list to learn more about it, and the details include a link to
install the app from AppSource.

See Also
Onboarding experiences in Business Central
Get the Outlook add-ins for the business inbox
2/6/2023 • 2 minutes to read • Edit Online

Business Central supports integration with Outlook so that users can complete Business Central business tasks
from their Outlook inbox.

Overview
The two add-ins for Business Central provide the following capabilities:
Contact insights
The add-in provides users with information from Business Central about their contacts in Outlook emails
and calendar appointments. It also enables users to create and send Business Central business
documents, such sales quotes and invoices to a contact. To support these tasks, the add-in adds actions to
the Outlook ribbon, in the Business Central group.
Create and view documents
When a business document is sent as an email, the add-in provides a direct link from email to the actual
business document in Business Central. The add-in adds a Document Links action in the email header,
which a user can select to display the document.
The processes for deploying the add-ins are different for Business Central online and on-premises, though the
add-ins are the same. So choose the right section to read from here on - use the links to the right to easily
navigate between the main sections.

Business Central online


For Business Central, the admin must configure the Microsoft 365 tenant to accept the two add-ins. You can
configure the tenant in two ways:
Centralized deployment of the add-ins
Centralized Deployment is a feature in Microsoft 365 admin center that you use to automatically install
add-ins in users' Office apps, like Outlook. It's the recommended way for admins to deploy for Office
add-ins to users and groups within your organization.
Automatic deployment of the add-ins
The automatic deployment requires you to register the add-ins as an app in Microsoft 365. This
effectively deploys the add-ins so that users can connect to Business Central from the Outlook app and
Outlook on the web.
For more information, see Get the Business Central Add-in for Outlook in the business functionality help.

Business Central on-premises


Setting up the add-ins for Business Central on-premises involves two procedures:
Configure the Business Central Server instance to work with the add-ins.
Then, you deploy the add-ins from the Business Central client and Microsoft 365 admin center to users'
Outlook.
For more information, see Set Up the Business Central Add-In for Outlook with Business Central On-premises.

Individual user deployment


If the add-ins aren't set up for deploy automatically, users can run the Get the Outlook Add-in assisted setup
in their Business Central to install both the Contact Insight and Document View add-ins.
For more information, see Install the add-in for your own use.

See Also
Using Business Central as your Business Inbox in Outlook
Set Up the Add-Ins for Outlook with Business Central on-premises
Deployment of Business Central on-premises
Using Business Central as your Business Inbox in Outlook
Preparing Your Network for the Excel Add-In
2/6/2023 • 2 minutes to read • Edit Online

As the administrator of Business Central online or on-premises, you can deploy an add-in so that users can work
with their Business Central data in the Excel desktop app. This article includes information that helps
administrators configure advanced device and network settings for the Excel add-in for Business Central when
your network requirements block the add-in.

Network endpoints required by the Excel add-in


The Excel add-in must have access to Business Central for it to function and synchronize business data. Network
services, such as proxies or firewalls, must allow routing between each client device on which the add-in is
installed and the following services that are published by Microsoft:
https://az689774.vo.msecnd.net
https://dc.services.visualstudio.com
https://exceladdinprovider.smb.dynamics.com
https://api.businesscentral.dynamics.com

NOTE
Your API endpoint URL can be different from these default values. For example, if your environment is based on a vertical
solution by Fabrikam, your API endpoint is https://fabrikam.api.bc.dynamics.com . These vertical solutions have API
endpoints that are based on the format of ApplicationName .api.bc.dynamics.com. You can check if an environment uses
such a URL in the Business Central Administration Center.

See also
Setting up the Excel Add-In for Editing Business Central Data
Administration of Business Central Online
Managing an Business Central Embed App in Microsoft Lifecycle Services
Setting up App Key Vaults for Business Central
Online
2/6/2023 • 3 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

AppSource apps for Business Central can be developed to get secrets from Azure Keys Vaults. The app key vault
feature is readily available for use on the service by all App Source apps. However, there are some onboarding
tasks required.

IMPORTANT
With Business Central online, App key vaults can only be used with AppSource apps. They're not supported with per-
tenant extensions.

TIP
You must also specify secrets in a key vault if you deploy Business Central as part of the Embed App program. Especially if
you must support the Outlook add-in, in which case you must specify secrets for
TEMPORARYDOCUMENTSTORAGEACCOUNT and TEMPORARYDOCUMENTSTORAGEKEY.

For more information about developing extensions with key vaults, see Using Key Vault Secrets in Business
Central Extensions.

Create the Azure Key Vault with secrets


In this task, you create a key vault in Azure, and add the secrets that you want to make available to your
extensions. An extension can use up to two key vaults, so you can create more than one.
There are different ways to create an Azure key vault. For example, you can use the Azure portal, Azure CLI, and
more.
The easiest way is to use the Azure portal. For instructions, see Quickstart: Set and retrieve a secret from Azure
Key Vault using the Azure portal.
For using other methods, see Azure Key Vault Developer's Guide.

Provision the key reader application in your Azure AD tenant


Your Business Central online solution is configured to use an Azure AD application for reading key vault secrets.
The application is called Dynamics 365 Business Central ISV Key Vault Reader . Microsoft manages the
key vault reader application, however, there are a couple tasks that you have to do to enable it. First, the
application must be provisioned on your Azure AD tenant, as described here.
To provision the key vault reader application, use the Azure Active Directory PowerShell module.
1. Open Windows PowerShell as an administrator.
2. Install the Azure Active Directory PowerShell module.
Install-Module AzureAD

3. Import the Azure AD module.

Import-Module AzureAD

4. Connect to your Business Central Azure AD tenant.


a. Run the following command:

Connect-AzureAD

b. Provide your sign-in name and password when prompted.


5. Create an Azure AD service principal using the following command:

New-AzureADServicePrincipal -AppId 7e97dcfb-bcdd-426e-8f0a-96439602627a

7e97dcfb-bcdd-426e-8f0a-96439602627a is the Application (client) ID of Microsoft's centralized Azure AD


application.
This step provisions the application in your Azure AD tenant, where it now "lives" together with your key
vaults.

Grant the key vault reader application permission to your key vaults
The next task is to grant the key vault reader application permission to read secrets from your key vaults. The
steps in this task are done from the Azure portal.
1. Open the key vault in the portal.
2. Select Access policies , then Add Access Policy .
3. Set Secret Permissions to Get .
4. Choose Select principal , and on the right, search for either the application (client) ID 7e97dcfb-bcdd-
426e-8f0a-96439602627a or the display name Dynamics 365 Business Central ISV Key Vault
Reader .
5. Select Add , then Save .

Contact Microsoft to enable the App Key Vault feature


Send an email to bcappkeyvaultonboard@microsoft.com to start the onboarding process following this
guideline:
If it is a new AppSource app, you should send the email after you have published the app on Partner
Center. When the app has been onboarded to the app key vault, you then need to publish a new version
of the app to Partner Center.
If it is an existing AppSource app, you can send the email at any time, but it will only take effect when you
publish a new version of the app to Partner Center.
The onboarding process involves a manual verification step that verifies that you own the AAD tenant that
contains the key vaults.
Provide the following information in the email:
Your AAD tenant ID. Obtain this information from the Azure portal by going to the Azure Active Directory
Overview page.
Your AppSource extensions, including names and App IDs, that should be enabled to read secrets from your
key vaults. Note: It is impor tant that all your AppSource extensions that need access to a key
vault are included, as it is not enough to just set the key vault proper ty in your app.json
manifest files.
Confirmation that the app is already published on AppSource.
Optionally, a screenshot from the Azure portal showing the key vault and its access policies. The screenshot
can help Microsoft catch configuration mistakes early in the process.

See Also
Security Considerations With App Key Vaults
Monitoring and Troubleshooting App Key Vaults
Configuring Business Central Server
Deploying a Tenant Customization
2/6/2023 • 3 minutes to read • Edit Online

When you have finished developing and testing your tenant customization, you must deploy the extension (.app
file) containing the customization to your customer’s production tenant. You must be able to log into the
customer’s tenant as a user with permissions to the Extension Management page to complete the
deployment.
Use the Upload Extension action to deploy the extension. The extension can be deployed for the current
version or for the next version of the service. In most cases it is sufficient to select the current version, unless
you have developed the extension specifically for the next version.

NOTE
When you deploy an .app file for the next version, the extension will be queued up to be deployed as part of the
customer’s tenant being upgraded to the next version. You can typically use this in a situation where you have built an
upgrade of the extension to work with the next version.

The extension you are deploying could be the initial release of the customization or an upgrade to a previous
version. You must use the same steps for uploading a new extension or an extension upgrade. The service will
determine if the extension needs to be upgraded based on the extension’s app ID and version.

Steps for deploying your .app file


1. Log into your customer’s Dynamics 365 Business Central tenant.
2. Open the Extension Management page.
3. Choose the Upload Extension action.
4. Select the browse button to select the .app file to upload. Browse to and select the extension’s .app file.
5. Select if you want to deploy for the current version (most common) or next version. Select the language for
the deployment.
6. Choose the Deploy button.
7. The extension will be deployed in the background.
To check the status of the deployment, choose Deployment Status and then view the status of the
extension deployment. Select the row to see additional details.
In the deployment status details there is a Refresh button in the actions you must press to retrieve the most
recent status and details.
8. When the extension has been successfully deployed, choose the Refresh button to see the new extension in
the list of installed extensions.

Extension uniqueness requirements


If you are developing and deploying an updated version of a previously-deployed extension, you must keep the
app ID the same and increase the version number to successfully upgrade the extension. The deployment
services require that uploaded extension packages be unique per tenant based on several sets of keys:
Package ID
App ID + Version
Name + Publisher + Version
NOTE
These parameters are defined in the app.json file of the extension. For more information, see JSON files.

If you have successfully deployed an extension to a tenant, and then recompile the extension’s source code
without updating version number, this generates a new extension package file with a new package ID. If you try
to upload this new extension package file to a different tenant, the upload will fail with the error similar to
An extension with same App ID and version has already been uploaded. Resolve and deploy again. . Similarly, if an
extension failed to deploy, and you try to upload a new extension package with the same version number, the
upload will fail as well.

Upgrades and per-tenant extensions


In some cases, a customer's production environment that includes a per-tenant extension cannot be upgraded
automatically by Microsoft. In those cases Microsoft contacts the reselling partner and provides guidance for
how to update the extension. However, if the extension remains impossible to upgrade, Microsoft will wait for 90
days and then uninstall the extension and force-upgrade the tenant.

See Also
Get Started with AL
AL Development Environment
FAQ for Developing in AL
Using Designer
Upgrading Per-Tenant Extensions that Conflicts with
Other Extensions
2/6/2023 • 4 minutes to read • Edit Online

In AL, all top-level objects are declared in the same global namespace. The extensions installed in an
environment cannot have the same top-level object declared multiple times or controls, fields, or dataitems with
the same name defined multiple times in the same logical object. This means that a table extension, for example,
cannot add a field with the same name as a field in the extended table. This topic shows how to upgrade an
extension which declares a table or a field that conflicts with a table or a field declared by another extension.

Two objects with the same name


If Extension A defines the following table

table 10 MyTable {}

And Extension B defines the table below

table 20 MyTable {}

Extension A and Extension B cannot be installed in the same environment because the two tables have the
same name. An error will be raised when the installation of the second extension is attempted and the
installation will fail.

Two objects with the same field name


If Extension A defines the following table and field

table 10 MyTable
{
field(1; MyField; Integer){}
}

And Extension B defines the table and field below

tableextension 20 MyTableExt extends MyTable


{
field(10; MyField; Boolean){}
}

Then Extension B will fail to compile because the field in the table extension has the same name as the field in
the base table. Publishing Extension B will fail with a compilation error.
In general, it is recommended using affixes for your object and element names to prevent this type of conflicts.
For more information, see Prefix and suffix for naming in extensions.

Example
To make the issue more concrete, the following example illustrates how this problem can manifest itself and
how to resolve it. In a Business Central environment running on Business Central 2020 release wave 1, update
16.5 (version 16.5), a per-tenant extension, named MyExtension by Contoso version 1.0.0.0 contains the
following table extension:

tableextension 50100 SalesCreditMemoHeaderExt extends "Sales Cr.Memo Header"


{
Fields
{
Field(50100; "Shipping Agent Service Code"; Code[10])
{
}
}
}

The table extension adds the field Shipping Agent Ser vice Code to the Sales Cr.Memo Header table
defined in the Base Application extension by Microsoft.
In Business Central 2020 release wave 2 (version 17.0), Microsoft enhances the table Sales Cr.Memo Header
by adding the following field:

field(5794; "Shipping Agent Service Code"; Code[10]) {}

The service will then attempt to upgrade the environment from version 16.5 to version 17.0 of the product.
During the upgrade process, the per-tenant extension will be recompiled against the latest version of the Base
Application . The compilation will fail with an error message similar to:
"A member of type Field with name "Shipping Agent Service Code" is already defined in Table "Sales Cr.Memo
Header" by the extension "Base Application by Microsoft (17.0.0.0)".
The service will now dismiss the upgrade of the environment and an email will be sent to the administrator
registered in the Tenant Administration Center containing the above error message.
The first reaction may be to modify the per-tenant extension, remove the conflicting field, and then try to upload
version 1.1.0.0 to the service. This will, however, fail with an error message similar to:
"Per-tenant extension "MyExtension" version 1.0.0.0 by "Contoso" failed to synchronize the database schema.".
This error message is raised because the system does not allow implicitly removing or renaming schema
elements such as tables and table fields. To upgrade the environment, it is necessary to forcefully remove the
conflicting field by following these steps:
1. Create a sandbox.
Because the following steps can lead to data-loss, it is recommended that the steps are first performed in a
sandbox environment created as a copy from the production environment. For more information, see Create
a new environment.
2. Export data using RapidStart.
Start by backing up the data contained in the tables or table extensions declared by the extension using
RapidStart. Use other mechanisms to backup the data, but the main point is to backup data to an external
storage system.
3. Uninstall the extension.
Uninstall the extension and select the option to delete the extension's data and schema. Using this option will
delete the tables and fields contributed by the table extension and the environment will delete any trace of
the extension.
4. Remove the field from the extension.
Create version 2.0.0.0 of the extension that does not contain the field which conflicts with the one from the
"Base Application". Deploy this version of the extension to the environment.
5. Import the data.
Import the data that has been backed up from the rapid start package or the external storage system used in
step 2.
6. Upgrade the environment.
At this point, the conflict is resolved and you should be able to update the environment. Schedule an update
for the sandbox and ensure it is successfully updated. If upgrade fails, troubleshoot the issue.
Once the sandbox environment has been successfully updated to the next release, steps 2-6 on the production
environment must be replicated. Before doing so, ensure that the customer will not be impacted by the changes
and clearly communicate a maintenance window in which the work will be performed.

See Also
Upgrading AppSource Apps in Production
Upgrading AppSource Apps in Production
2/6/2023 • 2 minutes to read • Edit Online

When an updated version of an AppSource app becomes the active version in the Dynamics 365 Business
Central service, tenants do not automatically get this updated version. This upgrade must be done manually by
getting the latest version of the app in AppSource.

To upgrade an AppSource app


Follow the steps below to update a tenant to the latest version of any AppSource app.
1. Log in to the Dynamics 365 Business Central browser client.
2. In the Tell Me box, enter Extension Management , and then choose the related link.
3. Locate the app that you want to update.
4. Under Manage , choose Uninstall .
5. Go to AppSource and then install the app again.

NOTE
An alternative, is to use the Admin Center, where you can also manage the upgrade, given that you have the right
permissions. For more information, see Managing Apps.

See Also
Developing Extensions
Get Started with AL
How to: Publish and Install an Extension
Set Up Company Configuration Packages
2/6/2023 • 10 minutes to read • Edit Online

As you grow your business as a reseller of Business Central, you will likely come to rely on a set of company
types that you use with most of your Business Central prospects. You can streamline your implementation
process by turning these types into configuration packages that are available for reuse.
After you have set up a company in Business Central that suits your needs, you can create a configuration
package that contains relevant setup data from this company. You can then use it when you create a new
company that is to be configured in the same way.
To facilitate the import of master data, such as customer and vendor information, you can use configuration
templates. Configuration templates contain a set of default settings that are automatically assigned to the
records imported into Business Central. Configuration templates are an alternative to the cloud migration tools
that you can use to migrate customer data from supported products. For more information, see Migrate On-
Premises Data to Business Central Online.

TIP
Use these capabilities to scale your business as a reseller. Most of the relevant pages apply to both Business Central online
and on-premises. However, some processes rely on access to the underlying database and are too complex to use for
Business Central online. For Business Central on-premises, you probably want to use Windows PowerShell to help you
deploy. For more information, see Administration of Business Central On-Premises and Administration of Business Central
Online, respectively.

Configuration packages
By default, Business Central online comes with one configuration package for Microsoft's default application,
including local functionality. You can copy that and make relevant changes in the copy.
Many of our reselling partners create a configuration package for each functional area. For example, create a
package for the manufacturing functionality and another for sales. That lets you apply and set up new areas in a
company as you need them.
We recommend that you create configuration packages with most of the setup tables already filled in, so that
only a few settings must be tweaked for each customer. For example, when you create a new company, the No.
Series and the No. Series Line tables are filled in with a set of number series and starting numbers. The
corresponding No. Series fields in the setup tables are also filled in automatically. You do not have to do the
work of entering number series and other basic setup data. You can also manually change all default data that is
used with RapidStart Services by using the configuration worksheet.
Another approach would be to create a package that includes the tables that define setup, such as the following:
General Ledger Setup
General Posting Setup
VAT Posting Setup
Inventory Posting Setup
Purchases and Payables Setup
Sales and Receivables Setup
Warehouse Setup
Inventory Setup
Manufacturing Setup
Fixed Asset Setup
Marketing Setup
Service Setup
To see a complete list of setup tables in Business Central, choose the icon, enter Manual Setup , and then
choose the related link.

TIP
Optionally, use the configuration worksheet to gather together and categorize the information that you want to use to
configure a new company, and arrange tables in a logical way. Formatting in the worksheet is based on a simple hierarchy:
areas contain groups, which in turn contain tables. Areas and groups are optional but useful. You can then add the
worksheet lines to a new configuration package.

Before you create a configuration package


There are some things to consider before you create a configuration package because they will impact you or
your customer's ability to import it.
Tables that contain posted entries
You cannot import data to tables that contain posted entries, such as the tables for customer, vendor, and item
ledger entries, so you should not include this data in your configuration package. You can add entries to these
tables after you import the configuration package by using journals to post the entries. For more information,
see Posting Documents and Journals in the business functionality content.
Table names that contain special characters
Use caution if you have tables or fields that have the same temporal name but are differentiated by special
characters, such as %, &, <, >, and ,. For example, a table might contain the Field 1 and Field 1% fields.
The XML processor that generates the .rapidstart files accepts only some special characters, and will remove
those it does not. If removing a special character, such as the % sign in "Field 1%," results in two or more tables
or fields with the same name an error will occur when you export or import a configuration package.
Permissions
The process of creating and importing a configuration package involves the following effective permissions for
all tables in the package:
The user who exports data for the configuration package must have Read effective permissions.
The user who imports the configuration package must have Inser t and Modify effective permissions.
Database schema
When exporting and importing configuration packages between two company databases, the databases must
have the same schema to ensure that all data is transferred successfully. This means that the databases should
have the same table and field structure, in which the tables have the same primary keys and fields have the
same IDs and data types. In practical terms, that means that your configuration package must be based on the
same version of Business Central as the customer environments that you intend to apply it to.
You can import a configuration package that has been exported from a database that has a different schema
than that target database. However, any tables or fields in the configuration package that are missing in the
target database will not be imported. Tables with different primary keys and fields with different data types will
also not successfully import. For example, if the configuration pack includes table 50000, Customer that has
primary key Code20 and the database to which you import the pack includes table 50000, Customer Bank
Account that has the primary key Code20 + Code 20 , then data will not be imported.

To create a custom company configuration package


1. Create a new company. For more information, see Create New Companies in Business Central in the
business functionality content.
2. Set up the new company in the way you need. Fill in all required setup tables.
Optionally, use the default configuration package in the Cronus demonstration company to set up the
base application. Then, add your own best practices on top.
Next, you'll add this setup to a configuration package. You can set up the tables that you want to add to
the package in the Configuration Worksheet page and then add a configuration package to the lines in
that worksheet. Or you can add the tables directly to the package in the Configuration Package page.
In the following steps, we assume that you prefer to set things up in the worksheet, but you don't have to.
3. Open the Configuration Worksheet page.
4. Add a new line of the type Area , and then add groups and the tables that you want to transfer to another
company to the package. Hover over a field to read a short description.

TIP
Take a look at the default configuration package for the demonstration company for inspiration for how to set up
the configuration.

a. Choose the Get Tables action. On the Get Config. Tables request page, specify the types of
tables that you want to add to the configuration, and set the relevant filters. Then choose the OK
button.
To exclude the configuration questionnaires, configuration templates, and configuration worksheet
tables from the package, select the Exclude Configuration Tables check box on the Config
Package Card page. Otherwise, these tables will be added to the list of package tables
automatically when you export the package.
b. To add related tables, choose the Get Related Tables action.

NOTE
Related tables will not be added with the Get Related Tables action if either of the following is true:
The relation is conditional.
Example: If you get related tables for the Customer table, then the Location table will not be added,
since it is only conditionally related to the Customer table, namely if the Location Code field in the
Customer table is filled in.
The related table is filtered.
Example: A field in the related table has a WHERE clause. The reason for this is that the involved
relations information is stored in the Field system table, which is not fully accessible to the application.
You must add such types of tables manually.

For each table, you can specify which fields to exclude, and you can modify the default processing
order for each field. Business Central checks if there are related fields that you must configure in
the Config. Package Fields page.
c. Optionally, for each table, modify which fields must be included in the package.
Select a table for which you want to specify field information, and on the Actions tab, in the Show
group, choose Fields .
To select just the fields you want to include, choose the Clear Included action. To add all fields,
choose the Set Included action.
To specify that the field data should not be validated, clear the Validate Field check box for the
field.
5. Assign the worksheet lines to an existing package.
a. Select the relevant lines, choose the Assign Package action, and then, in the Configuration
Packages page, choose the relevant package, or create a new one.
If a table is not already included in the package, it will now be added. The package code field on the
worksheet line will be filled in with the code of the package that the table is assigned to.
If you choose an existing package, you can see how many tables are already in the package by
reviewing the information in the No. of Tables field.
6. Optionally, create a questionnaire for the most frequently used setup tables so that you can get specific
information from your prospects and customers that will help you set up their Business Central.
a. On the Configuration Questionnaire page, add a new questionnaire, and then choose the
Questions Areas action.
b. In the Config. Question Area page, in the Table ID field, choose the ID of the table for which
you want to collect information. The Table Name field is automatically filled in.
c. Choose the Update Questions action. Each field in the table is added to the questionnaire with a
question mark following its caption in the Question field.
You can rephrase the question to make it clear that it is a question that should be answered. For
example, if a field is called Name , you could edit the related question to state What is the name of
the account. You can also provide guidance in the Reference field, including a URL to a page that
provides additional information for example.
You can also delete any questions that you do not want to include in the questionnaire.

NOTE
The Answer Option field describes the format that the answer to the question must meet, such as Code
or Text.
As needed, you can also define default answers in the Answer field. These values are used by default for
custom setup. However, the person filling in the questionnaire can modify and update the answer.

d. Repeat steps 2 and 3 for any additional areas that you want to add to the questionnaire, and then
return to the Configuration Questionnaire page.
Optionally, export the questionnaire to Excel. Then, you can use the Excel workbook to get answers
from your prospects and customers. There are worksheets for each of the question areas that have
been created for the questionnaire.

NOTE
You may encounter the following error when you run an English version of Excel, but have your regional
settings configured for a non-English language: Old format or invalid type library. To fix this error, make
sure that the language pack for the non-English language is installed.
7. Optionally, create configuration templates to make it easier to import master data, such as customers,
vendors, contacts, or items.
Use the built-in configuration templates, or create your own templates in the Configuration Templates
page. This is mainly useful if you're going to migrate customer data to Business Central on-premises and
then switch to the cloud. For more information, see Apply Company Configuration Packages.
You can export the templates as Excel workbooks so that you can work with customer data in Excel.
8. Export your package as a .rapidstart file, or export it to Excel.
The next time you're going to set up Business Central for a new customer, you can apply your configuration
packages and get started fast. For more information, see Apply Company Configuration Packages.

See Also
Apply Company Configuration Packages
Migrate On-Premises Data to Business Central Online
FAQ about Migrating to Business Central Online from On-Premises Solutions
Administration of Business Central Online
Administration of Business Central On-Premises
Get Started as a Reseller of Business Central Online
Onboarding experiences in Business Central
Apply Company Configuration Packages
2/6/2023 • 7 minutes to read • Edit Online

When you onboard a prospect, you can use configuration packages to set up Business Central according to your
best practices and their requirements. Apply the relevant configuration packages to an empty company in the
customer's tenant. Use the questionnaires to tweak things for individual customers of yours. Optionally, use
configuration templates to import existing customer data.
Start by setting up a company in a sandbox so that users can practice before they start using Business Central in
production.
If the customer needs more than one company in Business Central, you can copy commonly used values from
an existing company to a new one, as long as both companies are in the same tenant. For example, if you have a
standard list of symptom codes that is common to all your service management implementations, you can copy
the codes easily from one company to another. You can do this from the Configuration Worksheet page.

Migrate customer data


In many cases, to migrate customer data to Business Central online, use the built-in migration tools to migrate
data from specific product versions. For more information, see Migrate On-Premises Data to Business Central
Online.
Alternatively, you can migrate to Business Central on-premises using Excel or the data migration tools of
RapidStart Services, and then switch to the cloud.
You can choose to use the configuration package approach to migrating customer data, such as if the customer
is coming from a product that is not supported by the Migrate On-Premises Data to Business Central Online
tools, nor by an app for Business Central online, such as Microsoft's own apps to migrate from QuickBooks app.
From both the Configuration Worksheet page and the Configuration Package page, you can import data
from Excel or a .rapidstart file. If you prefer to use Excel, the data must be in an Excel workbook that is exported
from the Configuration Packages page. This way, the Excel workbook complies with the Business Central data
structure. In the Configuration Package page, you can map tables and fields if the data structure is different
between where the data came from and where it's going. Business Central treats and handles the mapping
based on table relations:
If you define a mapping directly for a field in a table, then Business Central uses it.
If the field has a relation to another table, Business Central searches for the mapping defined for the
primary key field in the related table. The related table, however, must be part of the configuration
package.
If mapping information is defined in both places, for the field directly and for the primary key in the
related table, then Business Central will search for the mapping in both places.
If the same mappings are defined directly for a field and in the related table, but have different new
values, the mapping that is defined directly for the field takes priority over the mapping that is defined for
the table that the field is referencing.
IMPORTANT
Use RapidStart configuration packages only when setting up a company for the first time. Configuration packages aren't
intended to be used for companies that are already in production. Using configuration packages to import large amounts
of data can impact performance and prevent all users from using Business Central during the process.
For companies that are in production, we strongly recommend that you use an XMLport to import and export data.
Learn more at XMLport Overview.

Import data from Excel


Use your configuration questionnaires and templates to map the existing data to Business Central in Excel.
Especially, make sure you capture master data about customers, items, vendors, and the general ledger.
If the customer comes from Business Central or Dynamics NAV, then you can export the customer's data to a
.rapidstart file and then import it into the new company. But in many cases, you'll want to work in Excel so that
you can tweak or map data.
To validate the configuration questionnaire
It is important to validate the configuration questionnaire before you apply it to the Business Central format. It is
also a way to make sure that data formatting is preserved during the import from Excel.
A common validation task is to check that text strings are not entered in date fields. This review process is
necessary because the format of the answer in the questionnaire is not validated automatically when you run
the Apply Answers function.

NOTE
In general, validation of the configuration questionnaire is a manual process. However, there are checks for regional
formatting inconsistencies. In addition, you will get errors if the structure of your Business Central database does not
match the structure of the migration database.

1. On the Configuration Questionnaire page, select the relevant questionnaire, and then choose the
Question Areas action.
2. Open the relevant question area.
3. For each question, validate that the value in the Answer field corresponds to the format provided in the
Answer Option field. For example, validate that the address of a company is in text format.
4. If you find errors, you can troubleshoot and make corrections in Excel by exporting the questionnaire, and
then importing it again. Alternatively, you can correct errors directly in Business Central as you review the
answers on the Config. Question Area page.
5. Repeat these steps for each question area.
When you have completed your validation, the data is ready to be applied to the database.
To apply answers from the configuration questionnaire
After you have imported and validated information from a configuration questionnaire, you can transfer, or
apply the setup data to the corresponding tables in the Business Central database.
1. Choose the icon, enter Configuration Questionnaire , and then choose the related link. The Config.
Questionnaire page opens.
2. Select a configuration questionnaire from the list, and then choose the Edit List action.
3. You can apply answers in one of two ways.
To apply the whole questionnaire, choose the Apply Answers action.
To apply answers for a specific Question Area only, choose the Question Areas action, select a Question
Area in the list, and then choose the Apply Answers action.
To verify that answers have been applied successfully
1. Check setup pages for the various functional areas of Business Central. To locate the page, choose the icon,
enter the name of the setup page, and then choose the related link.
2. Verify that the fields have been populated with the correct data from the various question areas in the
configuration questionnaire.
You have now configured setup with the customer’s business information and rules.
To import customer data
1. Open the Configuration Worksheet page or the Configuration Package page and import the
customer's master data.
In the No. of Package Errors field, see if there are any errors reported. If there are, drill down to see the
errors. The Config. Package Records page opens.
a. Choose the Show Error action. You will receive an error such as the following: XX is not a valid
option. Valid options are: XX. Choose the OK button.
b. To apply the mapping that you have set up, choose the Apply Data action.
2. Validate the migration
a. On the Migration Over view page, review the No. of Migration Errors field to see whether any
errors occurred during import.
b. If there are errors, select the migration table, and then, on the Tables tab, choose the Errors action.
The Invalid check box is selected for each record that has an error.
c. To review errors, select a line, and then choose the Show Error action.
The Error Text field contains the reason for the error. The Field Caption field contains the caption of the
field that contains the error.
4. To correct an error or otherwise make an update, on the Migration Over view page, choose the
Migration Record action, and then, on the Migration Record page, correct the record with the error.
Now, you have master data in place. Next, you add the opening balances. The following steps describe
how to create journal lines for G/L accounts, but the same apply to creating journal lines for customers,
vendors, and items.
3. Choose the Create G/L Acct. Journal Lines action.
4. Fill in the Options FastTab as appropriate, and set filters as needed. For example, in the Journal
Template field, enter a name.
5. Choose the OK button. The records are now in the journal, but the amounts are empty.
6. Export the journal table to Excel and manually enter the posting and balancing account information from
the legacy data.
7. Import and apply the table information into the new company. The journal lines are ready for posting.
8. In the configuration worksheet, select the journal line table, and then choose the Database Data action.
9. Review the information, and then choose the Post action.
10. Repeat the steps to import and post any other opening balances.
IMPORTANT
Specifically for opening balances for bank accounts, do not follow the steps in this article to post directly to the G/L
accounts that are associated with the relevant bank accounts. For more information, see Set Up Bank Accounts.

See Also
Set Up Company Configuration Packages
Migrate On-Premises Data to Business Central Online
FAQ about Migrating to Business Central Online from On-Premises Solutions
Administration of Business Central Online
Administration of Business Central On-Premises Get Started as a Reseller of Business Central Online
Onboarding experiences in Business Central
Trials and Sign-ups for Business Central Online
2/6/2023 • 5 minutes to read • Edit Online

As a reselling partner, you can invite customers and prospects to sign up for any number of Dynamics 365 apps,
including Business Central online and partner solutions based on Business Central, using the same account ID.
These apps will run side-by-side with each other, will use different URLs, and will be displayed as separate tiles
on the home.dynamics.com portal.
This means that you can show prospects a preview of what you are offering based on trials of Business Central
and other Dynamics 365 apps.
Adjust the onboarding checklist to fit your solution, and provide in-app tours for key experiences. For more
information, see Onboarding experiences in Business Central.

Prospects and trials


Prospects can contact you if they have signed up for the Business Central free trial. This means that you can
become their CSP partner. For more information, see Connect with customers.
Alternatively, you can create a more tailored trial environment based on the Business Central content pack on
the cdx.transform.microsoft.com site. For more information, see Preparing Demonstration Environments of
Dynamics 365 Business Central.
Some types of trials can be extended beyond 30 days. The following table outlines the types of trials that you
can offer prospects:

C A N B E USED F O R
SC EN A RIO T RIA L P ERIO D C A N B E EXT EN DED P RO DUC T IO N

Prospect signs up for the 30 days Yes Yes


free trial with their work or
school email account, and Once through the in-
then switches to My product notification + once
Company for a 30 day trial. by the partner

Their trial is based on the


Dynamics 365 Business
Central for IWs license.

Partner assigns the 30 days No Yes


Dynamics 365 Business
Central Premium Trial The partner can assign a
license to an existing client new Dynamics 365
in Partner Center so that Business Central
they can try out the Premium Trial license for a
Business Central full second 30 days trial
experience in My Company
C A N B E USED F O R
SC EN A RIO T RIA L P ERIO D C A N B E EXT EN DED P RO DUC T IO N

Partner creates a test 30 days No Yes


customer and assigns the
Dynamics 365 Business The partner can assign a
Central Premium Trial new Dynamics 365
license to that in Partner Business Central
Center. Then they invite a Premium Trial license for a
client or prospect to that second 30 days trial
trial.

At any point during their trial experience, when they are ready, you can convert their trial to a paid subscription
using the Partner Center dashboard. For more information, see Converting trials to paid subscriptions in the
Partner Center content.
Dynamics 365 Business Central Premium Trial
In the Partner Center, you can find a special license type called the Dynamics 365 Business Central
Premium Trial license, which is a very different way to give a prospect or an existing customer a trial
experience using their own data. If you assigned the Dynamics 365 Business Central Premium Trial license
to a customer's account in the Partner Center, then that also expires after 30 days. You cannot extend the
Premium trial, but you can add one more Premium trial license to give the customer an extra 30 days of trial.
But when the second Premium trial expires, then the customer must either convert their trial to a paid
subscription, or they must sign up for the viral trial.
For more information, see Offer your customers trials of Microsoft products in the Partner Center
documentation. If you have technical difficulties assigning this license, contact Partner Center support. For more
information, see Report problems with Partner Center.
Cau t i on

Make sure you understand the limitations of this type of trial, before you offer it to a prospect or customer. It is
easy to convert this type of trial to a paid subscription, but if the prospect needs more than 30 days to decide, or
if they want to add more than 25 users, then the viral trial is probably a better fit for them.
Extending trials
An organization can sign up for a free trial of Business Central. When they first sign up for Business Central, they
get access to an evaluation version that does not include all capabilities in Business Central. They can then
switch to the 30 day trial experience to enable all capabilities.
However, sometimes a 30 day trial is not enough to decide if they want to buy Business Central. In that case,
they can extend their trial with an additional 30 days. For more information, see Need More Time to Decide
Whether to Subscribe? in the business functionality content for Business Central.

NOTE
If you are a reselling partner, we recommend that you set up demo environments for prospects that need longer time to
decide if they want to buy Business Central. You can also use demo environments to help customers train their
employees, for example. Using the 30 days trials for training should be limited to just that short period. However, demo
environments cannot be used for production. For more information, see Preparing Demonstration Environments.

If the prospect wants to extend the trial further than those 30 days, they must contact a partner. The partner can
extend it another 30 days if the delegated administrator signs into the prospect's Business Central and runs the
Extend Trial Period guide.
After those additional 30 days, the prospect must either purchase Business Central or abandon Business Central.
At this point, they will have had up to 90 days with the trial experience.
TIP
As a reselling partner, you can suggest your prospects sign up for a trial, but you can also help set up a customized
demonstration environment based on a sandbox environment or a trial environment. In both cases, you can easily add or
remove functionality based on your prospects' expectations. For more information, see Preparing Demonstration
Environments.

Prepare demo environments


As a Business Central reselling partner, you might want to have an environment that you can show prospects as
part of pre-sales demonstrations. Depending on your requirements, you have several different options. For
more information, see Preparing Demonstration Environments.

Embed Apps and signing customers up


Specifically for partners that are in the Embed App program, signing up customers works differently. For more
information, see Onboarding customers and creating environments.

See Also
Onboarding experiences in Business Central
Help your customers get started
Get Started as a Reseller of Business Central Online
Embed App Overview
Major Updates and Minor Updates for Business Central Online
Onboarding experiences in Business Central
2/6/2023 • 2 minutes to read • Edit Online

Setting up Business Central for a customer usually involves manual setup from the partners' side. Often this
setup time is spent on basic settings that do not provide additional value to the specific customer but are more
generic and address the customer's industry or type of business. This is costly for the customer and can be a
bottleneck for you as a partner.
Microsoft provides tools you can use to help speed up this process and enable the customer to more easily learn
how to use the product and get to productive usage faster. This will save costs on the customer side and free up
your consultants' time.
The onboarding framework in Business Central presents all users with a consistent onboarding experience when
it comes to an introduction to the product itself. Partners can still use any other methodology that they prefer,
but the tools in the onboarding framework provides a native experience.

Onboarding elements at your disposal


In the following sections you find descriptions of components you can use when authoring onboarding
experiences for your customers along with guidance to where and how to use them.
Banner
For more information, see Onboard New Users with the Welcome Banner.
The checklist
For more information, see Get Users Started with the Checklist.
Teaching tips and tours
For information, see Teaching tips and in-app tours for onboarding users.

See also
Get Users Started with the Checklist
Onboard New Users with the Welcome Banner
Teaching tips and in-app tours for onboarding users
User Assistance Model
Extend and Collaborate on the Help
Migrate On-Premises Data to Business Central Online
Onboard New Users with the Welcome Banner
2/6/2023 • 2 minutes to read • Edit Online

When a user signs in to a new company for the first time, Business Central shows a welcome banner that
provides a clear call-to-action.

The purpose of the banner is to give users a warm and personal welcome, reduce noise, provide a clear call to
action to the get started tasks, without blocking users that wish to explore the product first.
The welcome banner works slightly different in CRONUS evaluation companies and in non-evaluation
companies, including My Company, because the banner serves different purposes in evaluation and non-
evaluation companies. The following sections outline the differences.

The welcome banner in CRONUS evaluation companies


In a CRONUS evaluation company, the banner serves the purpose of highlighting core capabilities of Business
Central to make the prospect excited and get them closer to subscribing to Business Central. By default, the
welcome banner points to capabilities that Microsoft has chosen to highlight in Business Central, such as a tour
of the Role Center and spotlight tours of integrations with Excel and Teams. Consider adding other key selling
point features to the checklist in CRONUS to aid you in selling Business Central. In CRONUS evaluation
companies, the banner cannot be hidden, only minimized. The banner is shown for the Business Manager
Evaluation role, which is the default profile for the person who signs into Business Central online. If that user
does not want to see the banner in CRONUS, they can switch to the Business Manager role. This switch happens
automatically when the user chooses to start the trial with their own data in My Company.

IMPORTANT
The Business Manager Evaluation role was created specifically for the design of the CRONUS evaluation experience. The
experience that is tied to this role through page customization or other directly impacted experiences may change from
release to release, unlike other code-related changes that are goverened by our breaking change rules.
We recommend that you build your own evaluation and demo experiences on another role if you want to make sure that
your scenarios are not impacted by these changes. For example, elements on the Business Manager Role Center has been
hidden for the Business Manager Evaluation role through page customization that is saved to the Business Manager
Evaluation role. More changes for the Role Center or other pages may come in the future for the Business Manager
Evaluation role based on Microsoft's need to pivot the CRONUS evaluation experience from the My Company experience.
The welcome banner in My Company and other non-evaluation
companies
In My Company and other non-evaluation companies, the welcome banner serves the purpose of letting the
customer self-serve the last-mile setup of Business Central. Accordingly, the checklist tasks are more focused on
guiding the user through various elements of setup. Consider how you structure the checklist for your
customers with the goal of getting them set up and onboarded as fast as possible.
For more information, see the Get Users Started with the Checklist article.

See also
Get Users Started with the Checklist
Teaching tips and in-app tours for onboarding users
Onboarding experiences in Business Central
Get Users Started with the Checklist
2/6/2023 • 6 minutes to read • Edit Online

When the user hits Get star ted on their Home page, a checklist is revealed inside the banner. The checklist
provides users with an overview of their onboarding activities, while allowing them to learn and explore at their
own pace. The checklist serves as a platform for surfacing page tours, guiding users in the product interface, and
teaching users how to use the app in context. The checklist provides a sense of progression, nudging users to
complete onboarding activities. Users can navigate between the tasks of the checklist at their own pace.
Checklist tasks can point to pages or objects in Business Central or point to external URLs. Read more about the
checklist content in the Prerequisites for creating checklist items section.
As the user progresses through the checklist by either completing or skipping the steps, the banner title and
status indication will change accordingly to nudge and encourage users to finish. At any point, the user can
minimize the banner by hitting X and resume when ready. The following illustration shows the checklist with the
suggested setup and learning material.

The checklist provides an overview of the tasks to complete as well as a detailed description of the ongoing task.
The following illustration shows a Business Central Home page with a collapsed banner, which indicates the
completion progress as well as providing a clear call-to-action to resume with the checklist activities.

What should go into a checklist


Checklists are meant to assist users in finalizing setup and help users get started with using the application.
Checklists are not meant to provide a full list of tasks necessary to set up Business Central from scratch. What
goes into the checklist depends on several factors, but consider bringing Configuration Packages with as much
base setup as possible so the checklist only consists of things where the customer needs to make tweaks and
decisions necessary to support their business. Automation APIs can help you with automating the delivery of
the setup for a customer's industry or segment and applying your IP from AppSource. Using these APIs you
should be able to automate much of the deployment process, including data for the checklist, which enables you
to hand over completion of the setup for the customer. Consider bringing Assisted Setup wizards for the things
that are added to the checklist.
Based on the configuration choices made by the customer in Assisted Setups, you can download additional
modular Configuration Packages necessary to complete the setup. This gives you a lot of flexibility to provide
setup based on customer choices at different stages of the implementation, with the key advantage for you and
the customer that you can spend less time on the actual implementation.

NOTE
The checklist has different purposes in evaluation and non-evaluation companies. Consider this when you add content to
the checklist. For more information, see Onboard New Users with the Welcome Banner].

Technical background of the checklist


The data model of the checklist consists of the following tables. There are more in the data model but these are
the ones you need to know about to provide onboarding experiences to customers.

ID NAME P URP O SE

1991 Checklist Item Represents the checklist item itself.

1992 Checklist Item Role Represents the mapping of checklist


items to roles.

1993 Checklist Item User Represents the mapping of checklist


items to named users.

Prerequisites for creating checklist items


Before you can make a checklist item point to an entity or URL you must add a record to the Guided
Experience Item table that refers to the desired entity.

Guided Experience Item


From the Dynamics 365 Business Central 2021 release wave 1 the records in Manual Setup and Assisted
Setup are migrated to a new table, Guided Experience Item . This table has a field, Type , that determines the
type of each record:
Assisted Setup
This is where all assisted setup wizards now reside.
Manual Setup
This is where all manual setup records now reside.
Learn
Records of type Learn point to an external URL.
Tour
Records of type Tour point to a tour of the role center. Currently, these can only be added by Microsoft in
the Business Central platform. We are considering enabling AL developers to add and control these tours
in time.
Spotlight Tour
Records of type Spotlight Tour point to a special kind of tour where Business Central opens a page in a
special mode that suppresses other tours and shines a bright spotlight on core capabilities, such as Open
in Excel or Share to Teams. Use the spotlight tour in sales and evaluation scenarios to show off key
capabilities that will get customers excited about the product. Consider how you can use these spotlights
for your own or other features. The following illustration shows a spotlight tour that calls out Teams and
Excel integration on a page.

The spotlight tour suppresses teaching tips on the page and immediately calls out Teams and Excel
integration features as shown in the following illustration.

Video
Records of type Video enables the user to watch a video provided by a custom URL. The video will play
in a window inside Business Central. Consider how you can utilize video to explain a feature or capability.
Video is normally used in a sales/evaluation scenario but could also be used for training purposes in an
onboarding case. The following illustration shows a video player that is started from the checklist.
Application Feature
Records of type Application Feature enables a checklist task to open any page inside Business Central.
Similar to Manual Setup this opens a page and will display a page tour if any is defined.
Checklist items can be based on records in the Guided Experience Item table, which means that before you
surface a task on the checklist, you must first add it to Guided Experience Item .
To insert a record in the Guided Experience Item table use the façade functions in the Guided Experience
codeunit:
InsertManualSetup
InsertAssistedSetup
InsertLearnLink
InsertTour
InsertSpotlightTour
InsertVideo
InsertApplicationFeature

For example, let's say that you have the page My ISV Solution Setup where the user can configure your app.
You want to invite the business manager to access this page from the checklist. In this example, you must insert
a new record in the Guided Experience Item table with the type Manual Setup and provide the metadata as
data (title, descriptions, and so on) as described below.
After having created this record, it can now be referenced from and inserted into a checklist.
Best practices for checklist content creation
Do:
Keep the list short (preferably 6 items or less) to avoid a scrollbar and to ensure a successful start for
users.
Keep checklist titles and descriptions short and to the point.
When writing the description, it's good practice to include the benefit of doing the task. But be brief.
TIP
If the task points to a page that comes from the manual setup list, the Shor tTitleChecklist is picked from there. Those
titles consist of nouns such as User permissions .
If the task points to wizards that comes from the assisted setup list, the LongerTitleCard is picked from there. Those
titles usually contain a verb such as Update users .

Don't:
Don't overwhelm the user with a long list of checklist tasks
Don't use too long titles as they're harder to understand and space becomes an issue.
Maximum character UX guideline
Checklist: Shor tTitleChecklist : Max 34 characters before truncation.
Checklist: LongerTitleCard : Max 53 characters before truncation.
Checklist: CardDescription: Max 180 characters before truncation
Client truncation limits
Checklist: Shor tTitleChecklist : Max 34 characters before truncation.
Checklist: LongerTitleCard : Max 53 characters before truncation.
Checklist: CardDescription: A scrollbar appears if the description renders as more than 4 lines.
Auto completion settings and time estimates
Add support for auto-completion when possible, such as for wizards, as this automatically makes the
checklist move to the next task and provides the user with a good sense of progress.
Provide a realistic time stamp of the estimated completion time and strive for tasks that take less than 5
minutes to complete.

See also
Teaching tips and in-app tours for onboarding users
Onboarding experiences in Business Central
Teaching tips and in-app tours for onboarding users
2/6/2023 • 9 minutes to read • Edit Online

A key element in educating users about Business Central pages and concepts is the tour. A tour is a sequence of
teaching tips.
Teaching tips can be defined at the page level, the page teaching tip, and be followed by teaching tips at the
control level, the control teaching tips. Both types of teaching tips are defined by the .AL properties AboutTitle
and AboutText , and an extension can overwrite teaching tips in the default version.

Page teaching tips


The primary purpose is to increase the user's chance of success with the page. So, the title and
description of the page teaching tip should answer the following hypothetical user questions:
AboutTitle : What is this page about?
AboutText : What can I do with this page?
Teaching tips explain Business Central logic that is relevant to the page.
Teaching tips let users discover and initiate the related tour whenever they are ready for it.
Allow users to get on with a task right away without blocking them.
A teaching tip can be defined for any page in Business Central, except the role centers, dialogs, and
request pages for reports.
After users dismiss a teaching tip and tour, they can choose or hover over the page title. This action will
reopen the teaching tip, and the user can retake the tour, for example.
On a page that is opened from the checklist, the tour is considered an invited tour, and the page teaching
tip has a Go back button that takes the user back to the checklist.
The following illustration shows a page teaching tip that explains what the page is about and can invite the user
to take a tour. The teaching tip renders in the lower left corner.

The following illustration shows how choosing the page title will reopen the teaching tip so that the user can
retake the tour.
How to write page teaching tips
There are different rules for teaching tips for lists versus cards and documents.

L IST PA GE W IT H T EA C H IN G T IP C A RD PA GE W IT H T EA C H IN G T IP

AboutTitle : About sales invoices AboutTitle : About sales invoice details


AboutText : Sales invoices appear in this list until they're AboutText : You can update and add to the sales invoice
finalized and posted. After an invoice is posted, find it again until you post it. If you leave the invoice without posting,
in the Posted Sales Invoices list. you can return to it later from the list of ongoing invoices.

Answers the following questions: Answers the following questions:

What can I do on this page in general? What can I do on this page with this particular field
or action?
Is there a related entity I should know about?
What is the desired outcome of the task in this page?
The title for a list page teaching tip will typically use
the plural form, such as About sales invoices The title for a card or document page teaching tip will
typically be [entity name] + details, such as About
sales invoice details

What you should know about tours


Tours are sequential teaching tips describing functionality while pointing to elements in the UI.
The tour guides the user around the page.
Tours can be initiated from the page teaching tip
During a tour, a page with input fields will be in read mode.
Tours show where to find something, what it is, what it means, what you can do with it, and what it
affects.
A control teaching tip can point out a value that the user must check to know their next step.
Example: The Status field on an invoice. When the status is open, the user can edit the invoice.
A control teaching tip can describe the relevant timing for when to use a field or action.
Example: The Post action: When done editing, then post and send.

How to write teaching tips for controls


There are different rules for teaching tips for input fields and actions.

T EA C H IN G T IP P O IN T IN G TO A N IN P UT F IEL D T EA C H IN G T IP P O IN T IN G TO A N A C T IO N

AboutTitle: Who you are selling to Content example for the Post action:
AboutText: This can be an existing customer, or you can AboutTitle: When all is set, you post
register a new from here. Customers can have special prices AboutText: After entering the sales lines and other
and discounts that are automatically used when you enter information, you post the invoice to make it count. After
the sales lines. posting, the sales invoice is moved to the Posted Sales
Invoices list.

The teaching tip can point to a field that may or may With multiple similar actions,such as Post and Post
not have data. & New , call out the simplest version only.

A control teaching tip can explain an important Avoid action language that tells users to do
value's meaning, such as what leaving the field blank something that isn't active during the tour. Don't say:
does. Now post the invoice. Instead, explain what to be
aware of when posting.
Avoid stating the obvious and avoid action language
that tells users to do something that isn't active
during the tour. For example, don't say Enter the
customer name here. Instead, explain what to be
aware of when adding a customer.

Teaching tips for FactBoxes


INTRODUCED IN: Business Central 2021 release wave 2

You can add teaching tips for FactBoxes just like pages by using the AboutTitle and AboutText properties is AL.
Adding teaching tips to FactBoxes
Teaching tips are supported on all page types that are supported in FactBoxes, including pages that display cues.
Specifically, you can add teaching tips to following elements:
On the part control that contains the page or cue.
The page or cue that is included in the part control.
Controls, like fields, on the page or cue.
When adding teaching tips, consider the following limitations:
You can't add teaching tips to actions or control add-ins in FactBoxes.
For FactBox teaching tips to activate, the hosting page must have a page teaching tip. The page doesn't need
any control teaching tips.
How FactBox teaching tips fit into tours
The teaching tips for FactBoxes become part of the tour on the hosting page. For more information, see Teaching
tips flow.

Teaching tips flow


When designing teaching tips for a tour, it's important to understand the order in which teaching tips appear.
The flow is as follows:
1. Content area of the main page
a. Page teaching tip
b. Control teaching tips
2. Action bar of the main page
3. FactBoxes
a. Part control teaching tip
b. Page teaching tip
c. Control teaching tips
4. System teaching tips. These teaching tips are for standard features that added are added by the platform and
aren't controlled by AL.

Rich text guidelines for teaching tips


APPLIES TO: Business Central 2022 release wave 1 and later

2022 release wave 1 adds support for rich text formatting for teaching tips. In this section, we take a look at the
rules and guidelines to follow when using rich text in teaching tips, such as bold, italic, or links.
Bold
Bolded text can call out the most important points, such as
Page names, such as Customer Card
Key features, such as Search
Field names, such as Customer
Keyboard shortcuts, such as Alt+Q
Best practices for use of bolded text
Use bolded text sparsely to avoid "shouting".
If a page name or key feature is title cased, it might be a candidate. However, consider if using bold is
needed to help understanding the message.
Consider the difference between a page name such as the **Posted Sales Invoices** list (bolded and
capitalized page name) as opposed to what the list contains such as the list of posted invoices (not
capitalized and not bolded).
If the feature is already mentioned in the title, consider if it's necessary to highlight the word again in the
body text. Bolding a word once in a tip is usually enough.

Italics
Italic text can be used to bring attention to key terms or field values, such as the following:
Key term, such as general ledger
Field value, such as Closed

Links to open pages


Adding links to page teaching tips can be relevant in the following cases:
Links can be added to page teaching tips, to help users discover a key related page in Business Central, such
as linking to the Item Templates page from a teaching tip on the Items list page.
Best practices for use of links
Use links sparsely and use only in page teaching tips. It may be confusing to send users elsewhere.
Don't use links in tour teaching tips, as it will disrupt the tour experience.
The following illustration shows a page teaching tip with a link to guide users to a related page in Business
Central, such as the Posted Sales Invoices list, that users might be looking for in the Sales Invoices list.
Common pitfalls
When you want to call out page names with bold, make sure only the caption is marked, such as
**Sales Invoice** page or **Sales Invoices** list . In these examples, "page" and "list" don't have and
shouldn't have rich text applied.
Don't apply multiple rich text styles to the same word. Apply one type of formatting only, bold, italic, or a
link.

Tooltips and control teaching tips are complementary


There are different rules for tooltips and teaching tips.

TO O LT IP P O IN T IN G AT A F IEL D C A P T IO N T EA C H IN G T IP P O IN T IN G TO A F IEL D

Guidance for tooltips: Guidance for control teaching tips:

Every field and action has a tooltip. Only the most important fields/actions have a
teaching tip.
Answers the question What is this?
Answers the question What can I do with this field or
Relevant for everything since every field/action has a action?
definition.
Isn't relevant for every field/action.

Teaching tips guides users to fields/actions to be


discovered and focus on.

For more information about tooltips, see Help users get unblocked.

Best practices for teaching tips and tours


Not all pages in Business Central need teaching tips and tours. Use teaching tips where they provide
value.
A teaching tip says what can be done (outcome), not how to do it (steps)
A teaching tip is short, and easily read. Usually just two or three short sentences.
Do
Use easy to understand titles that are relevant to the element being pointed to.
Be concise with the information you provide in a teaching tip. Short sentences or sentence fragments are
best.
Keep the tour as short as possible with 1-4 steps.
Titles with a question are OK to use, but use them sparingly.
Use positive cases, don't tell what you can't do.
Follow Microsoft voice guidelines
Don't
Don't provide how-to (steps) or instructional guidance in teaching tips. That content lives on
learn.microsoft.com or in your own documentation.
Don't use large, unformatted blocks of text in a teaching tip.
Don't put obvious tip text, or text that simply repeats what is already on the screen.
If you can't find anything to say, maybe reevaluate if this teaching tip is needed.

See also
Get Users Started with the Checklist
Guidelines for tooltip text
Onboarding experiences in Business Central
AboutTitle Property
AboutText Property
Pivot onboarding based on sign-up context
2/6/2023 • 2 minutes to read • Edit Online

You can create onboarding experiences that depend on where the Business Central sign-up originated. This
origin is defined as the sign-up context , which is available in version 20.3 and later.
Business Central passes this sign-up context from the browser URL to the application where it can be processed
by AL code. The sign-up context is visible to apps that want to react to the sign-up context to vary the
functionality according to the context.
Let's look at an example where a sign-up is triggered by a user on the Shopify administration page. Shopify
users can choose to sign up to Business Central after they installed the Business Central app on Shopify. The
Business Central sign-up flow is triggered, and the sign-up context is passed along to Business Central by the
client and exposed to AL for apps to consume.

How the sign-up context works


A URL string is added to the sign-up URL that contains a signupContext parameter and a payload of key-value
pairs. Let's look at the example where a user has signed up from Shopify:

_%3D1%26signupContext%3D%7B%22name%22%3A%22shopify%22%7D_

The encoded characters will end up resolving to a URL such as the this one:

https://businesscentral.dynamics.com/?redirectedFromSignup=1&ScenarioId=signup&signupContext={name:shopify}

Business Central recognizes the sign-up context parameter and stores the key-value pairs in a system table. The
key-value pairs are then parsed by the Business Central application and added to a database table, Signup
Context Values , for consumption.
During the sign-in process, an event is triggered that allows subscribing apps to read the Signup Context
Values table at an appropriate moment to run code that modifies the user experience where needed based on
the context.

IMPORTANT
Only sign-up contexts that are known to the Business Central application, created by Microsoft, will be parsed and
transferred from the system table to the app table. At this moment we do not recommend partners to attempt to use
the sign-up context.

Which sign-up contexts exists


Currently, two sign-up contexts exist:
viral
This context is provided when users sign up to Business Central from the Microsoft marketing web pages.
shopify
This context is provided when users sign up to Business Central via the Shopify administration web site.
Can partners add more sign-up Contexts?
Not at the moment. However, we're considering how to enable partner-driven scenarios by the use of other
sign-up contexts.

See also
Onboarding experiences in Business Central
Recommend Apps
2/6/2023 • 2 minutes to read • Edit Online

The Microsoft commercial marketplace offers a wide variety of apps from Microsoft and our partners that
extend the value of Business Central. As a Microsoft partner, you can save yourself, and your customers, a bit of
legwork by using the Recommended Apps extension to curate a list of apps that are right for your customers'
businesses. Recommended Apps is a per-tenant extension (PTE), which means that you can make collections
unique for each customer, or build collections specifically for certain types of businesses or industries and then
reuse the collections when you're on-boarding those types of customers. For example, you can create one
collection for customers who work in finance, and another for customers in the retail space. For more
information, see Maintain AppSource Apps and Per-Tenant Extensions in Business Central Online.

Before you begin


You can only add apps that are available on AppSource to your collection. That is, you cannot host your own app
and add it to the list.

Building a collection of recommended apps


Building collections requires some development. To make that easier, Business Central provides the following
objects:
Recommended Apps List page
Recommended App Card page
Recommended Apps table
Recommend Apps codeunit
You must use the Recommend Apps codeunit to build collections. The following table provides an overview of
the methods in the codeunit. You can copy the information for the parameters from the listing for the app on
AppSource.

M ET H O D DESC RIP T IO N

Inser tApp Add information about the apps from AppSource to the
Recommended Apps table. When adding new apps, you can
simply paste the URL for the app from AppSource for the
AppSourceUrl parameter, and Business Central will add the
relevant parts to the other parameters. However, you must
manually complete the Short Description ,
Long Description , and Recommended By parameters.

GetApp Get information from AppSource about the apps that are
already added to the Recommended Apps table.

UpdateApp Update the information about the apps that are already
added to the Recommended Apps table.

RefreshImage Update the logo for the app. When you insert an app, the
image is downloaded automatically. Use if the logo has
changed.
M ET H O D DESC RIP T IO N

DeleteApp Delete an app from the collection. You provide the app ID.

DeleteAllApps Delete all apps from the collection.

GetAppURL Get the URL for a specific app. You provide the app ID.

Providing the collection to customers


When your collection is ready, you can deploy it to customer tenants. For more information, see Deploying a
Tenant Customization. Afterward, the Recommended Apps page will display the apps and your customer can
install them. Customers can choose the app in the list to learn more about it, and the details include a link to
install the app from AppSource.

See Also
Onboarding experiences in Business Central
Monitoring and Analyzing Telemetry
2/6/2023 • 6 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

Business Central emits telemetry data for various activities and operations on environments and
apps/extensions. Monitoring telemetry gives you a look at the activities and general health of your
environments/apps, so you can diagnose problems and analyze operations that affect performance. Azure
Application Insights is a service hosted within Azure that gathers telemetry data for analysis and presentation.
Whether running Business Central online or on-premises, you can set your tenants up to send telemetry to
Azure Application Insights.

Environment-level and app/extension-level telemetry


Telemetry can be enabled on two different levels:
Environment
Telemetry can be enabled for a Business Central online environment or on-premises Business Central
Server instance. When enabled on the environment, telemetry is emitted to a single Azure Application
Insights resource for gathering data on operations that happen on the environment.
App/Extension
With the Business Central 2020 release wave 2 and later, telemetry can also be enabled on a per-
extension basis. Enabling telemetry is done by setting an Azure Application Insights connection string in
the app's manifest (app.json file). At runtime, certain events related to the app/extension are emitted to
the Azure Application Insights resource. This feature targets publishers of per-tenant extensions or
Appsource apps to give them insight into issues in their app/extension before partners and customers
report them.
Both for environment-level and app-level telemetry, it's possible to craft custom telemetry messages directly
from AL using the LogMessage Method. Learn more about AL at Programming in AL.

Available telemetry
Currently, Business Central offers telemetry on the following operations:

EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

AppSource Provides See...


Submission information
Validation about validation
when an
extension is
submitted to
AppSource.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

App key vault Provides [1] [1] See...


secrets information
about the
retrieval of
secrets from
Azure Key Vaults
by extensions.

Authorization Provides See...


information
about user sign-
in attempts.
Information
includes success
or failure
indication,
reason for
failure, user type,
and more.

Azure Function Provides See...


Integration[6] information
about requests
to Azure
Functions from
Business Central

Company Provides See...


lifecycle information
about creating,
copying, and
deleting of
companies.

Configuration Provides See...


package lifecycle information
about operations
done on
configuration
packages,
including
exporting,
importing,
applying, and
deleting.

Database Provides See...


deadlocks[5] information
about database
deadlocks that
occur.

Database lock Provides See...


timeouts information
about database
locks that have
timed out.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Database wait Provides See...


statistics information
about the wait
categories and
the wait times a
query runs into.

Email Provides See...


information
about the
success or failure
of sending
emails.

Environment Provides See...


lifecycle [5] information
about changes
and operations
on an
environment, like
updates,
hotfixes, copy,
move, delete,
configuration
changes,and
more.

Error message Provides See...


quality[5] information
about error
messages that
users thought
were helpful or
unhelpful.

Error method Provides See...


information
about error
dialogs that are
shown to the
users.

Extension Provides See...


lifecycle [2] information
about the
success or failure
of extension-
related
operations, like
publishing,
synchronizing,
installing, and
more.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Extension update Provides See...


information
about errors that
occur and
upgrade tags
used when
upgrading an
extension.

Feature Provides See...


telemetry information
about the usage
and errors of
features.

Field monitoring Provides See...


trace information
about the usage
of the field
monitoring
feature.

Job queue Provides See...


information
about creating
and running job
queue entries.

Long running AL Provides See...


method trace[3] information
about long
running AL
methods.

Long running Provides See...


operation (SQL information
query) about SQL
queries that take
longer than
expected to
execute.

Page views Provides [6] [4] See...


information
about the pages
that users open
in the modern
client.

Permissions Provides See...


information
about adding,
removing, and
assigning
permission sets.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Permissions Provides See...


dependency information
cycle[5] about
dependency
cycles in
permissions.

Permission Provides See...


error[5] information
about errors
related to
permissions that
users get.

Profile Provides See...


configuration information
lifecycle[6] about design
operations done
on profiles from
the client.

Report Provides See...


generation information
about the
execution of
reports.

Retention policy Provides See...


trace[3] information
about the usage
of the retention
policy feature.

Incoming web Provides See...


service requests information
about the
execution time of
incoming web
service requests.

Outgoing web Provides See...


service requests information
about the
execution time of
outgoing web
service requests.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Stopped Provides See...


sessions[5] information
about
background
sessions that
were forcibly
stopped from
the admin center
or by calling the
StopSession
method from AL.

Table index Provides See...


trace[3] information
about the
addition or
removal of a
table index.

Task scheduler Provides See...


lifecycle information the
execution of
scheduled tasks.

User checklists[5] Provides See...


information
about when the
status of a user
checklist changes

Verbose logging Provides See...


enabled/disabled information
[5] about when
additional
logging is
enabled and
disabled from
the client.

Web service Provides See...


access key information
authentication about the
authentication of
web server
access keys on
web service
requests.

This signal is only emitted to the Application Insights resource that's specified in the extension.
2

Introduced in Business Central 2020 release wave 1, version 16.3. For extension telemetry, this signal was
introduced in 2020 release wave 2, version 17.1.
3

Introduced in Business Central 2020 release wave 1, version 17.1. For extension telemetry, this signal was
introduced in 2021 release wave 1, version 18.1.
4

Introduced in Business Central 2021 release wave 1, version 18.


5

Introduced in Business Central 2022 release wave 1, version 20.


6

Introduced in Business Central 2022 release wave 2, version 21.

Enable Telemetry
To send telemetry data to Azure Application Insights, you must have an Application Insights resource in Azure.
Once you have the Azure Application Insights resource, you can start to configure your environments and
apps/extensions to send telemetry data to it. Learn more at Enable Sending Telemetry to Application Insights.

NOTE
For apps/extensions, see Sending Extension Telemetry to Azure Application Insights.

Control telemetry cost


Azure Application Insights is billed based on the volume of telemetry data that is sent (data ingestion) and how
long time you want data to be available (data retention).
Check the Azure Application Insights documentation for up-to-date information on pricing at
https://azure.microsoft.com/pricing/details/monitor/.
For more information, go to Control Telemetry Cost.

Viewing telemetry data


Telemetry from Business Central is stored in Azure Application Insights Logs in the traces and pageViews tables.
You can view collected data by writing log queries using Kusto query language (KQL). Learn more at Logs in
Azure Monitor and Overview of log queries in Azure Monitor.
For more information, go to Analyze Telemetry with KQL.

Setting up alerts on telemetry


If something happens in your environment or app that you need to act on, you can set up a system that sends
you an alert. Azure Application Insights makes it easy to define such alerts.
You can use the following tools to define and set up alerts on telemetry events:
Azure Application Insights Alerts
Azure Logic Apps
Power Automate
All three approaches need a Kusto (KQL) query to define the alerting condition.
For more information, go to Alert on Telemetry.

Telemetry sample code


To make it easier to get started using Azure Application Insights with Business Central, samples of KQL code are
available in the Business Central BCTech repository on GitHub.

Business Central telemetry FAQ


The Business Central BCTech repository on GitHub has an extensive FAQ on Business Central telemetry in Azure
Application Insights.

See also
Telemetry Event IDs
Enable Sending Telemetry to Application Insights
Working with Administration Tools
Business Central Administration Center
Managing Environments
Managing Tenant Notifications
Introduction to Automation APIs
LogMessage Method
Available telemetry
2/6/2023 • 13 minutes to read • Edit Online

In Application Insights, telemetry from Business Central is logged into the traces or pageview tables.

Telemetry by area
Currently, Business Central offers telemetry on the following operations:

EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

AppSource Provides See...


Submission information
Validation about validation
when an
extension is
submitted to
AppSource.

App key vault Provides [1] [1] See...


secrets information
about the
retrieval of
secrets from
Azure Key Vaults
by extensions.

Authorization Provides See...


information
about user sign-
in attempts.
Information
includes success
or failure
indication,
reason for
failure, user type,
and more.

Azure Function Provides See...


Integration[6] information
about requests
to Azure
Functions from
Business Central

Company Provides See...


lifecycle information
about creating,
copying, and
deleting of
companies.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Configuration Provides See...


package lifecycle information
about operations
done on
configuration
packages,
including
exporting,
importing,
applying, and
deleting.

Database Provides See...


deadlocks[5] information
about database
deadlocks that
occur.

Database lock Provides See...


timeouts information
about database
locks that have
timed out.

Database wait Provides See...


statistics information
about the wait
categories and
the wait times a
query runs into.

Email Provides See...


information
about the
success or failure
of sending
emails.

Environment Provides See...


lifecycle [5] information
about changes
and operations
on an
environment, like
updates,
hotfixes, copy,
move, delete,
configuration
changes,and
more.

Error message Provides See...


quality[5] information
about error
messages that
users thought
were helpful or
unhelpful.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Error method Provides See...


information
about error
dialogs that are
shown to the
users.

Extension Provides See...


lifecycle [2] information
about the
success or failure
of extension-
related
operations, like
publishing,
synchronizing,
installing, and
more.

Extension update Provides See...


information
about errors that
occur and
upgrade tags
used when
upgrading an
extension.

Feature Provides See...


telemetry information
about the usage
and errors of
features.

Field monitoring Provides See...


trace information
about the usage
of the field
monitoring
feature.

Job queue Provides See...


information
about creating
and running job
queue entries.

Long running AL Provides See...


method trace[3] information
about long
running AL
methods.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Long running Provides See...


operation (SQL information
query) about SQL
queries that take
longer than
expected to
execute.

Page views Provides [6] [4] See...


information
about the pages
that users open
in the modern
client.

Permissions Provides See...


information
about adding,
removing, and
assigning
permission sets.

Permissions Provides See...


dependency information
cycle[5] about
dependency
cycles in
permissions.

Permission Provides See...


error[5] information
about errors
related to
permissions that
users get.

Profile Provides See...


configuration information
lifecycle[6] about design
operations done
on profiles from
the client.

Report Provides See...


generation information
about the
execution of
reports.

Retention policy Provides See...


trace[3] information
about the usage
of the retention
policy feature.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Incoming web Provides See...


service requests information
about the
execution time of
incoming web
service requests.

Outgoing web Provides See...


service requests information
about the
execution time of
outgoing web
service requests.

Stopped Provides See...


sessions[5] information
about
background
sessions that
were forcibly
stopped from
the admin center
or by calling the
StopSession
method from AL.

Table index Provides See...


trace[3] information
about the
addition or
removal of a
table index.

Task scheduler Provides See...


lifecycle information the
execution of
scheduled tasks.

User checklists[5] Provides See...


information
about when the
status of a user
checklist changes

Verbose logging Provides See...


enabled/disabled information
[5] about when
additional
logging is
enabled and
disabled from
the client.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Web service Provides See...


access key information
authentication about the
authentication of
web server
access keys on
web service
requests.

This signal is only emitted to the Application Insights resource that's specified in the extension.
2

Introduced in Business Central 2020 release wave 1, version 16.3. For extension telemetry, this signal was
introduced in 2020 release wave 2, version 17.1.
3

Introduced in Business Central 2020 release wave 1, version 17.1. For extension telemetry, this signal was
introduced in 2021 release wave 1, version 18.1.
4

Introduced in Business Central 2021 release wave 1, version 18.


5

Introduced in Business Central 2022 release wave 1, version 20.


6

Introduced in Business Central 2022 release wave 2, version 21.

Telemetry by Event Id
The following tables list the Ids of Business Central telemetry events that are emitted into Azure Application
Insights.
Application events
EVEN T ID A REA M ESSA GE

AL0000CTV Email Email sent successfully

AL0000CTE Field monitoring Sensitive field value has changed:


{alfieldCaption} ({alFieldNumber}) in
table {altableCaption}
({alTableNumber})

AL0000CTP Email Failed to send email

AL0000DD3 Field monitoring Sensitive field monitor status has


changed to {almonitorStatus}

AL0000EMW Field monitoring Sensitive field added to or removed


from monitor: {alfieldCaption}
({alFieldNumber}) in table
{alTableCaption} ({alTableNumber})
EVEN T ID A REA M ESSA GE

AL0000E2A Permissions User-defined permission set added:


{alPermissionSetId}

AL0000E2B Permissions User-defined permission set removed:


{alPermissionSetId}

AL0000E28 Permissions Permission set link added:


{alSourcePermissionSetId} ->
{alLinkedPermissionSetId}

AL0000E29 Permissions Permission set link removed:


{alSourcePermissionSetId} ->
{alLinkedPermissionSetId}

AL0000E2C Permissions Permission set assigned to user:


{alPermissionSetId}

AL0000E2D Permissions Permission set removed from user:


{alPermissionSetId}

AL0000E2E Permissions Permission set assigned to user group:


{alPermissionSetId}

AL0000E2F Permissions Permission set removed from user


group: {alPermissionSetId}

AL0000D3L Retention Policy Retention Policy Log Entry Logged:


{alMessageType}

AL0000D6H Retention Policy Records Deleted Using Retention


Policy: Deleted {alRecordsDeleted}
records from Table {alTableNo},
{alTableName}

AL0000D6I Retention Policy First retention policy enabled on:


{alCompanyName}

AL0000D6J Retention Policy Last retention policy disabled on:


{alCompanyName}

AL0000I74 Azure Function Integration Request sent to Azure function


succeeded: {Function Host}

AL0000I75 Azure Function Integration Authorization failed to Azure function:


{Function Host}

AL0000I7P Azure Function Integration Request sent to Azure function failed:


{Function Host}

Client events
EVEN T ID A REA M ESSA GE

CL0001 Page views Page opened: {alObjectName}


EVEN T ID A REA M ESSA GE

CL0002 UI quality User gave feedback on error message:


[OK|Not OK]

Lifecycle events
EVEN T ID A REA M ESSA GE

AL0000E24 Job Queue Lifecycle Job queue entry enqueued:


{alJobQueueId}

AL0000E25 Job Queue Lifecycle Job queue entry started:


{alJobQueueId}

AL0000E26 Job Queue Lifecycle Job queue entry finished:


{alJobQueueId}

AL0000E3F Configuration Package Configuration package export started:


{alPackageCode}

AL0000E3G Configuration Package Configuration package exported


successfully: {alPackageCode}

AL0000E3H Configuration Package Configuration package import started:


{alPackageCode}

AL0000E3I Configuration Package Configuration package imported


successfully: {alPackageCode}

AL0000E3N Configuration Package Configuration package apply started:


{alPackageCode}

AL0000E3O Configuration Package Configuration package applied


successfully: {alPackageCode}

AL0000E3P Configuration Package Configuration package deleted


successfully: {alPackageCode}

AL0000EJ9 Extension Lifecycle Upgrade tag searched for:


{AlUpgradeTag}

AL0000EJA Extension Lifecycle Upgrade tag set: {AlUpgradeTag}

AL0000EIQ User Checklist Lifecycle User checklist status updated:


{oldStatus} to {newStatus}

LC0001 Company Lifecycle Company created: {companyName}

LC0002 Company Lifecycle Company creation canceled:


{companyName}

LC0003 Company Lifecycle Company creation failed:


{companyName}
EVEN T ID A REA M ESSA GE

LC0004 Company Lifecycle Company copied:


{companyNameSource} to
{companyNameDestination}

LC0005 Company Lifecycle Company copied canceled:


{companyNameSource} to
{companyNameDestination}

LC0006 Company Lifecycle Company copy failed:


{companyNameSource} to
{companyNameDestination}

LC0007 Company Lifecycle Company deleted: {companyName}

LC0008 Company Lifecycle Company deletion canceled:


{companyName}

LC0009 Company Lifecycle Company deletion failed:


{companyName}

LC0010 Extension Lifecycle Extension installed successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0011 Extension Lifecycle Extension failed to install:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0012 Extension Lifecycle Extension synchronized successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId}

LC0013 Extension Lifecycle Extension failed to synchronize:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0014 Extension Lifecycle Extension published successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0015 Extension Lifecycle Extension failed to publish:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0016 Extension Lifecycle Extension un-installed successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})
EVEN T ID A REA M ESSA GE

LC0017 Extension Lifecycle Extension failed to un-install:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0018 Extension Lifecycle Extension unpublished successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0019 Extension Lifecycle Extension failed to un-publish:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0020 Extension Lifecycle Extension compiled successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0021 Extension Lifecycle Extension failed to compile:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0022 Extension Lifecycle Extension updated successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher}

LC0023 Extension Lifecycle Extension failed to update:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0024 Table Index Lifecycle Index enabled: {tableName}

LC0025 Table Index Lifecycle Index disabled: {tableName}

LC0026 Extension Lifecycle Dependent Extension installed


successfully: {extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0027 Extension Lifecycle Dependent extension un-installed


successfully: {extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0028 AppSource Submission AppSource submission validation


request started: {validationRequestId}

LC0029 AppSource Submission AppSource submission validation


request completed successfully:
{validationRequestId}
EVEN T ID A REA M ESSA GE

LC0030 AppSource Submission (Version, country-region) validation


started: version {version},
country/region {countryRegion}

LC0031 AppSource Submission (Version, country-region) validation


completed successfully: version
{version}, country/region
{countryRegion}

LC0032 AppSource Submission Extension validation started: version


{version}, country/region
{countryRegion} for extension
{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0033 AppSource Submission Extension validation completed


successfully: version {version},
country/region {countryRegion} for
extension {extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0034 AppSource Submission Validation diagnostic reported: version


{version}, country/region
{countryRegion} for extension
{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0035 AppSource Submission AppSource submission validation


request completed with failures:
{validationRequestId}

LC0036 AppSource Submission (Version, country-region) validation


completed with failures: version
{version}, country-region
{countryRegion}

LC0037 AppSource Submission Extension validation completed with


failures: version {version}, country-
region {countryRegion} for extension
{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0038 AppSource Submission Diagnostic reported on AppSource


submission validation request:
{validationRequestId}

LC0040 Task Scheduler Task {taskId} created:


{codeunitObjectId} scheduled to run
after {notBefore}. Ready to run:
{isReady}

LC0041 Task Scheduler Task {taskId} ready: {codeunitObjectId}


set ready to run after {notBefore}.
EVEN T ID A REA M ESSA GE

LC0042 Task Scheduler Task {taskId} removed:


{codeunitObjectId}.

LC0043 Task Scheduler Task {taskId} main/failure codeunit


{codeunitObjectId} completed.

LC0044 Task Scheduler Task {taskId} main/failure codeunit


{codeunitObjectId} canceled.

LC0045 Task Scheduler Task {taskId} main/failure codeunit


{codeunitObjectId} failed.

LC0046 Profile Configuration Lifecycle Profile import succeeded: {ProfileId} in


app/extension {ProfileAppId}

LC0047 Profile Configuration Lifecycle Profile import failed: {ProfileId} in


app/extension {ProfileAppId}

LC0048 Profile Configuration Lifecycle Profiles exported successfully

LC0049 Profile Configuration Lifecycle Profiles failed to be exported

LC0050 Profile Configuration Lifecycle Profile copy succeeded: {ProfileId} to


{NewProfileId} from app/extension
{ProfileAppId} to app/extension
{NewProfileAppId}

LC0051 Profile Configuration Lifecycle Profile copy failed: {ProfileId} to


{NewProfileId} from app/extension
{ProfileAppId} to app/extension
{NewProfileAppId}

LC0052 Profile Configuration Lifecycle Profile created successfully: {ProfileId}


in app/extension {ProfileAppId}

LC0053 Profile Configuration Lifecycle Profile removed: {ProfileId} in


app/extension {ProfileAppId}

LC0054 Profile Configuration Lifecycle Profile page customization removed:


{ProfileId} in app/extension
{ProfileAppId}

LC0055 Profile Configuration Lifecycle Profile page customization converted:


{ProfileId} in app/extension
{ProfileAppId}

LC0056 Extension Lifecycle Extension is already synchronized:


{extensionName}

LC0100 Environment Environment update available for


scheduling: {environmentName} to
version {destinationVersion}.
EVEN T ID A REA M ESSA GE

LC0101 Environment Environment update scheduled:


{environmentName} to version
{destinationVersion}, update on or
after date:
{registeredForUpdateOnOrAfterDateUt
c}

LC0102 Environment Environment update missed:


{environmentName} to version
{destinationVersion}

LC0103 Environment Environment update postponed:


{environmentName} to version
{destinationVersion}

LC0104 Environment Environment update resumed:


{environmentName} to version
{destinationVersion}

LC0105 Environment Environment update started:


{environmentName} to version
{destinationVersion}

LC0106 Environment Environment updated successfully:


{environmentName} to version
{destinationVersion}

LC0107 Environment Environment failed to update:


{environmentName} to version
{destinationVersion}

LC0110 Environment Environment restart operation


initiated: {environmentName}

LC0111 Environment Environment restarted successfully:


{environmentName}

LC0112 Environment Environment restart operation failed:


{environmentName}

LC0113 Environment Environment start operation initiated:


{environmentName}

LC0114 Environment Environment started successfully:


{environmentName}

LC0115 Environment Environment start operation failed:


{environmentName}

LC0116 Environment Environment stop operation initiated:


{environmentName}

LC0117 Environment Environment stopped successfully:


{environmentName}
EVEN T ID A REA M ESSA GE

LC0118 Environment Environment stop operation failed:


{environmentName}

LC0119 Environment Environment copy operation started


on source: {environmentName} to
{destinationEnvironmentName}

LC0120 Environment Environment copied successfully:


{environmentName} to
{destinationEnvironmentName}

LC0121 Environment Environment copy operation failed on


source: {environmentName} to
{destinationEnvironmentName}

LC0122 Environment Environment copy operation started


on destination: {environmentName}
from {sourceEnvironmentName}

LC0123 Environment Environment copied successfully to


destination: {environmentName} from
{sourceEnvironmentName}

LC0124 Environment Environment copy operation failed on


destination: {environmentName} from
{sourceEnvironmentName}

LC0125 Environment Environment point-in-time restore


operation started on source:
{environmentName} to
{destinationEnvironmentName}

LC0126 Environment Environment point-in-time restored


successfully: {environmentName} to
{destinationEnvironmentName}

LC0127 Environment Environment point-in-time restore


operation failed on source:
{environmentName} to
{destinationEnvironmentName}

LC0128 Environment Environment point-in-time restore


operation started on destination:
{environmentName} from
{sourceEnvironmentName}

LC0129 Environment Environment point-in-time restored


successfully to destination:
{environmentName} from
{sourceEnvironmentName}

LC0130 Environment Environment point-in-time restore


operation failed on destination:
{environmentName} from
{sourceEnvironmentName}
EVEN T ID A REA M ESSA GE

LC0131 Environment Environment move to


{destinationAadTenantId} AAD tenant
operation scheduled to run at
{registeredForMoveDateUtc}:
{sourceEnvironmentName}

LC0132 Environment Environment move to


{destinationAadTenantId} AAD tenant
operation scheduling failed:
{sourceEnvironmentName}

LC0133 Environment Environment move to


{destinationAadTenantId} AAD tenant
operation started:
{sourceEnvironmentName}

LC0134 Environment Environment moved to


{destinationAadTenantId} AAD tenant
successfully: {sourceEnvironmentName}

LC0135 Environment Environment move to


{destinationAadTenantId} AAD tenant
operation failed:
{sourceEnvironmentName}

LC0136 Environment Environment session {sessionId}


cancellation started:
{environmentName}

LC0137 Environment Environment session {sessionId}


cancelled successfully:
{environmentName}

LC0138 Environment Environment session {sessionId}


cancellation failed: {environmentName}

LC0139 Environment Environment database export


operation started: {environmentName}

LC0140 Environment Environment session {sessionId}


cancelled successfully:
{environmentName}

LC0141 Environment Environment session {sessionId}


cancellation failed: {environmentName}

LC0142 Environment Environment configuration key


{environmentConfigurationKey}
updated for environment
{environmentName} to value:
{newValue}

LC0143 Environment Environment configuration key


{environmentConfigurationKey} failed
to update for environment
{environmentName}
EVEN T ID A REA M ESSA GE

LC0144 Environment Environment configuration key


{environmentConfigurationKey}
deleted for environment
{environmentName}

LC0145 Environment Environment configuration key


{environmentConfigurationKey} failed
to delete for environment
{environmentName}

LC0146 Environment Environment update window was


modified for environment:
{environmentName}

LC0147 Environment Environment update window


modification failed for environment:
{environmentName}

LC0149 Environment Environment delete operation started:


{environmentName}

LC0150 Environment Environment deleted successfully:


{environmentName}

LC0151 Environment Environment delete operation failed:


{environmentName}

LC0152 Environment Environment rename operation


started: {environmentName}

LC0153 Environment Environment renamed successfully:


{environmentName}

LC0154 Environment Environment rename operation failed:


{environmentName}

LC0155 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion}
scheduled for environment:
{environmentName}

LC0156 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion}
scheduling failed for environment:
{environmentName}

LC0157 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion} was
cancelled for environment:
{environmentName}
EVEN T ID A REA M ESSA GE

LC0158 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion} started
for environment: {environmentName}

LC0159 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion} applied
successfully for environment:
{environmentName}

LC0160 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion} failed for
environment: {environmentName}

LC0161 Extension Lifecycle Environment app {extensionName}


install to version
{extensionDestinationVersion}
scheduled for environment:
{environmentName}

LC0162 Extension Lifecycle Environment app {extensionId}, version


{extensionDestinationVersion}
installation scheduling failed for
environment: {environmentName}

LC0163 Extension Lifecycle Environment app {extensionId}, version


{extensionDestinationVersion}
installation started for environment:
{environmentName}

LC0164 Extension Lifecycle Environment app {extensionName},


version {extensionVersion} installation
succeeded for environment:
{environmentName}

LC0165 Extension Lifecycle Environment app {extensionName},


version {extensionDestinationVersion}
installation failed for environment:
{environmentName}

LC0166 Extension Lifecycle Environment app {extensionName},


version {extensionDestinationVersion}
installation/update requires
automatically installing a new
dependency app
dependencyExtensionName}, version
{dependencyExtensionDestinationVersi
on} for environment:
{environmentName}

LC0167 Extension Lifecycle Environment app {extensionName}


update to version
{extensionDestinationVersion}
scheduled for environment:
{environmentName}
EVEN T ID A REA M ESSA GE

LC0168 Extension Lifecycle Environment app {extensionId} update


to version
{extensionDestinationVersion}
scheduling failed for environment:
{environmentName}

LC0169 Extension Lifecycle Environment app {extensionId} update


to version
{extensionDestinationVersion} started
for environment: {environmentName}

LC0170 Extension Lifecycle Environment app {extensionId} update


to version
{extensionDestinationVersion}
succeeded for environment:
{environmentName}

LC0171 Extension Lifecycle Environment app {extensionId} update


to version
{extensionDestinationVersion} failed for
environment: {environmentName}

LC0173 Extension Lifecycle Environment app {extensionName}


uninstall scheduled for environment:
{environmentName}

LC0174 Extension Lifecycle Environment app {extensionId}


uninstall scheduling failed for
environment: {environmentName}

LC0175 Environment Environment data upgrade operation


started: {environmentName}

LC0176 Environment Environment data upgrade operation


completed successfully:
{environmentName}

LC0177 Environment Environment data upgrade operation


failed: {environmentName}

LC0178 Environment Recovery from a failed data upgrade


operation has completed successfully:
{environmentName}

LC0179 Environment Recovery from a failed data upgrade


operation has failed:
{environmentName}

Runtime events
EVEN T ID A REA M ESSA GE

RT0001 Authorization AuthorizationFailed(PreOpenCompany)


: {failure reason}
EVEN T ID A REA M ESSA GE

RT0002 Authorization Authorization Failed (Open Company):


{failure reason}

RT0003 Authorization AuthorizationSucceeded(PreOpenCom


pany)

RT0004 Authorization Authorization Succeeded (Open


Company)

RT0005 Performance Operation exceeded time threshold


(SQL query)

RT0006 Report generation Success report generation

RT0006 Report generation Report rendering failed: {report ID} -


{report name}

RT0007 Report generation Cancellation report generation

RT0008 Incoming Web service requests Web service called ({category of


request}): {endpoint}

RT0010 Extension lifecycle Extension Update Failed: exception


raised in extension {extensionName} by
{extensionPublisher} (updating to
version {extensionTargetedVersion})

RT0011 Report generation Report cancelled but a commit


occurred

RT0012 Performance Database lock timed out

RT0013 Performance Database lock snapshot: {snapshotId}

RT0014 Security App Key Vault initialization succeeded:


'{keyVaultUri}'

RT0015 Security App Key Vault initialization failed

RT0016 Security App Key Vault secret retrieval


succeeded from key vault
'{keyVaultUri}'

RT0017 Security App Key Vault secret retrieval failed


from key vault: '{keyVaultUri}'

RT0018 Performance Operation exceeded time threshold (AL


method)

RT0019 Outgoing Web service requests Web Service Called (Outgoing):


{endpoint}
EVEN T ID A REA M ESSA GE

RT0020 Web service key request Authentication with Web Service Key
succeeded: {endpoint}

RT0021 Web service key request Authentication with Web Service Key
failed: {endpoint}

RT0023 Troubleshooting Verbose telemetry enabled for session:


{sessionId}

RT0024 Troubleshooting Verbose telemetry disabled for session:


{sessionId}

RT0025 Performance Database wait statistics snapshot


taken: {snapshotId}

RT0026 Performance Database wait statistics snapshot


entry: {databaseWaitStatisticsCategory}

RT0028 Performance Database deadlock occurred

RT0029 Sessions The StopSession method was invoked


on session {failureReason}

RT0030 Error method call Error dialog displayed: {errorMessage}

RT0031 Permission error Permission error shown

RT0032 Permission error Dependency cycle discovered in


permission sets

See also
Telemetry Event IDs
Enable Sending Telemetry to Application Insights
Enable Environment Telemetry
2/6/2023 • 5 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

This article describes how to set up sending telemetry data to Azure Application Insights for Business Central
online and on-premises environments.

NOTE
For app/extension telemetry, see Sending Extension Telemetry to Azure Application Insights.

Get started (set up Azure Application Insights)


1. If you don't already have one, get a subscription to Microsoft Azure.
2. Sign in to the Azure portal.
3. Create an Azure Application Insights resource by following the guidelines at Workspace-based
Application Insights resources.

IMPORTANT
In Business Central 2020 release wave 2 (v17) and earlier, don't use an Azure Application Insights resource in
Germany regions, such as (Europe) Germany West Central or (Europe) Germany Nor th . If you do, traces
from Business Central might not be recorded in Application Insights. The mitigation is to create an Azure
Application Insights resource in a region outside of Germany. Then, when the relevant time comes, move the
resource to the preferred region.

The Azure Application Insights resource can be in any Azure tenant that is accessible to your organization.
For example, a delegated administrator from the reselling partner is the person analyzing the telemetry.
But this person might not have access rights the customer's Azure instance. This scenario enables the
partner to send the telemetry to their own Azure Application Insights instance.

TIP
You can use the same Azure Application Insights resource for multiple tenants and their different environments.

For more information, see Create an Application Insights resource.


4. Depending on your Business Central version, get the Connection String or Instrumentation Key of
the Azure Application Insights resource.
You can copy this information from the Over view page for resource in the Azure portal.
For Business Central 2020 release wave 2 (v17) or earlier, copy the Instrumentation Key .
For later versions, copy the Connection String . The maximum supported length for the
connection string is 2,048 characters.
NOTE
For these versions, you can use either the instrumentation key or the connection string. However, for
reliability, we recommend that you use the connection string.

NOTE
Transition to using connection strings for data ingestion in Application Insights by 31 March 2025 . On
31 March 2025, technical support for instrumentation key–based global ingestion in the Application
Insights feature of Azure Monitor will end. After that date, your Azure Application Insights resources will
continue to receive data, but Microsoft no longer provide updates or customer support for
instrumentation key–based global ingestion.

Enable telemetry on environments


Once you have the resource and its connection string or instrumentation key, you can enable your tenants to
send telemetry to your Azure Application Insights resource.
The way you enable Azure Application Insights depends on whether you want to connect to a Business Central
online or Business Central on-premises environment. For on-premises, if also depends on whether the Business
Central Server instance is configured as a single-tenant or multitenant instance.
For online environments
For Business Central online, you can enable telemetry on environments either from the admin center or by
using the the admin center API. To use the admin center, complete the following steps. For information about
using the admin center API, go to Put AppInsights key.
From the admin center
1. In the Business Central administration center, select Environments , and then select the environment that
you want to change.

IMPORTANT
The next steps require a restart to the environment, which is triggered automatically at the end of this procedure.
Plan to do this during non-working hours to avoid disruptions.

2. On the Environment page, the Application Insights Key field shows if the environment already uses
application insights.
To enable telemetry, choose the Define caption, and then, in the Set Application Insights Key pane,
choose the Enable application insights field and enter the instrumentation key in the
Instrumentation Key field.

NOTE
In version 15 and 16, to enable telemetry, choose the Application Insights Key action, and then specify the
instrumentation key.

3. Choose the Save button.


For on-premises environments (single -tenant mode )
For a single-tenant server instance of Business Central on-premises, set the Application Insights Connection
String or Application Insights Instrumentation Key setting of the server instance.
Set-NAVServerConfiguration -ServerInstance BC200 -Keyname ApplicationInsightsConnectionString -Keyvalue
'InstrumentationKey=11111111-2222-3333-4444-555555555555;IngestionEndpoint=https://westeurope-
1.in.applicationinsights.azure.com/'

For more information, see Configuring Business Central Server.


For on-premises environments (multi-tenant mode )
For a multitenant server instance of Business Central on-premises, enable telemetry on a per-tenant basis when
you mount tenants on the Business Central Server instance.
The Mount-NAVTenant cmdlet includes the -ApplicationInsightsConnectionString and -ApplicationInsightsKey
parameters. For example:

Mount-NAVTenant -ServerInstance BC200 -Tenant tenant1 -DatabaseName "Demo Database BC (20-0)" -


DatabaseServer localhost -DatabaseInstance BCDEMO -ApplicationInsightsConnectionString
'InstrumentationKey=11111111-2222-3333-4444-555555555555;IngestionEndpoint=https://westeurope-
1.in.applicationinsights.azure.com/'

or

Mount-NAVTenant -ServerInstance BC200 -Tenant tenant1 -DatabaseName "Demo Database BC (20-0)" -


DatabaseServer localhost -DatabaseInstance BCDEMO -ApplicationInsightsKey 11111111-2222-3333-4444-
555555555555

If you use the same Azure Application Insights resource for multiple environments, consider also using the
AadTenantId parameter to distinguish tenants in telemetry.
For on-premises Docker sandbox environments
If you're using the BcContainerHelper module, specify the Azure Application Insights instrumentation key when
you create the container. The key is used on the server instance for a single-tenant container. For a multi-tenant
container, it's used on the default tenant.

New-BcContainer `
-accept_eula `
-updateHosts `
-artifactUrl (Get-BCArtifactUrl -country us) `
-applicationInsightsKey "11111111-2222-3333-4444-555555555555"

You can specify the same or another key when creating more tenants:

New-BcContainerTenant -tenantId "additional" -applicationInsightsKey "11111111-2222-3333-4444-555555555555"

Assign a telemetry ID to users


To help troubleshooting problems experienced by a given Business Central user, you can assign the user a
random ID that will be included in traces logged in Application Insights. This ID is a special GUID that's only used
for telemetry. It will appear in the user_Id column in certain events, but not all. Specifically, it's used only in
telemetry that the Business Central service/server emits in the context of a user session. So, for example,
telemetry that the Business Central Web server emits won't include this ID.
To assign, change, or clear the telemetry ID on a user, set the Telemetr y ID field on the User Card for the user
in Business Central:
1. Sign in to Business Central using an administrator account.
2. Choose the icon, enter Users , and then choose the related link.
3. Choose the user name to open the User Card page.
4. Select the Telemetr y ID field .

.
To assign or change the telemetry ID, choose Set field to random GUID > OK .
To clear the telemetry ID, choose Set field to null GUID > OK .

NOTE
We recommend that a telemetry ID is assigned to all users to make it possible to troubleshoot situations that happened
in the past using telemetry.

Cleaning up settings
If the Azure Application Insights resource is tied to your partner account, and you end the relationship with a
customer where you have set up telemetry based on your account's instrumentation key, you must remove the
instrumentation key while you still have access to that customer's Business Central administration center.
It is also considered good practice to change all user telemetry IDs at the end of the relationship with the
customer. This will remove traceability to users for all data in the Azure Application Insights resource.

See Also
Sending Extension Telemetry to Azure Application Insights
Monitoring Long Running SQL Queries
Environment Telemetry
Monitoring and Analyzing With Telemetry
Controlling Telemetry Cost
2/6/2023 • 4 minutes to read • Edit Online

Azure Application Insights is billed based on the volume of telemetry data your application sends (data
ingestion) and how long time you want data to be available (data retention).
Check the Azure Application Insights documentation for up-to-date information on pricing:
https://azure.microsoft.com/pricing/details/monitor/.

Control data ingestion cost


To reduce data ingestion cost, you can:
sample to only ingest a percentage of the inbound data (learn more at Sampling in Application Insights.
set a daily limit of how much data can be ingested
set alerts on cost thresholds being exceeded to get notified when it happens
use a custom endpoint (go to section)
Except for using a custom endpoint, you find the options for controlling data ingestion cost in Azure Application
Insights, under configure, usage, and estimated costs.
Distribution of telemetry data
The easiest way to see the data distribution of different event IDs in your Azure Application Insights resource is
to use the Data in Telemetry page on the Administration report in the Power BI app on telemetry data.
You can also run the KQL queries below.

// 30 day overview of event ingestion in your Application Insights resource


let lookback = 30d ;
let traces_stats =
traces
| where timestamp > ago(lookback)
| extend eventId = tostring( customDimensions.eventId )
| summarize count() by eventId
| extend table_name = 'traces'
| project eventId, table_name, count_
;
let pageview_stats =
pageViews
| where timestamp > ago(lookback)
| extend eventId = tostring( customDimensions.eventID )
| summarize count() by eventId
| extend table_name = 'pageViews'
| project eventId, table_name, count_
;
traces_stats
| union pageview_stats
| order by count_ desc
| project eventId, table_name, event_count=count_
| order by event_count desc

Similarly, you can see the data distribution of different environments in your Azure Application Insights
resource, by running the KQL queries below.
// 30 day overview of data ingestion by environment in your Application Insights resource
let lookback = 30d ;
union traces, pageViews
| where timestamp > ago(lookback)
| extend aadTenantId = tostring( customDimensions.aadTenantId )
, environmentName = tostring( customDimensions.environmentName )
| summarize count() by aadTenantId, environmentName
| project aadTenantId, environmentName, count_
| order by aadTenantId, environmentName

Use data collection rules (DCR )


Azure Log Analytics (the backend of Azure Application Insights) has a feature called Data Collection Rules (DCR).
DCRs allow you to define rules on what is ingested into your telemetry resource. Use them to filter away
unneeded telemetry data, which speeds up query performance and saves cost.
To use DCRs, your Azure Application Insights resource must be converted to Workspace-based (which enables
Log Analytics as your back end). For recently created Azure Application Insights resources, Workspace-based is
the default setting. For older Azure Application Insights resources, you need to convert them (takes a few
minutes).
DCRs are defined on your workspace under the menu item Tables. Business Central currently logs to two tables:
AppTraces and AppPageViews. These tables are the back-end tables for the tables traces and pageviews that you
normally use in KQL queries. Right-click on a table and go to Edit transformation and select the
Transformation Editor button to add a KQL query to filter away certain types of data.
To help you get started with setting up Data Collection Rules, we added many sample KQL queries that illustrate
common filter scenarios:
how to filter out one or more events (I don't need these events, no need to pay for them)
how to only filter part of an event (I only want to see events when something fails or I only want 10 percent
of these events)
how to filter on Azure AD tenant (I'm an ISV and I want to start slowly on telemetry, so only enabling it for a
few customers)
how to filter on environment type (I'm an ISV and I only want data from production environments)
how to filter on app dimensions (I'm a VAR and this app/publisher is too noisy)
For sample queries, go to Data Collection Rule KQL samples.
Use a custom endpoint
Azure Application Insights support overriding the standard data ingestion endpoint provided in the connection
string (available in the Azure Application Insights portal). This capability means you can send telemetry data to
your own component to do post-processing. For example, you could filter or enrich before ingesting data into
your data source of choice. The data source can be an Azure SQL database, a data lake, Azure Log Analytics,
Azure Application Insights, or a third-party data store.
You can override the ingestion endpoint by using the IngestionEndpoint key in the Azure Application Insights
connection string. Learn more in the documentation: Overriding the Azure Application Insights standard
connection string.

Reducing data retention cost


To reduce data retention cost, you can
use the default retention for Azure Application Insights resources (currently 90 days). Different retention
periods can be selected for each Application Insights resource. The full set of available retention periods is 30,
60, 90, 120, 180, 270, 365, 550, or 730 days.
purge data from your Application Insights resource using a set of user-defined filters. See Components -
Purge for examples.

See also
Telemetry overview
Enabling telemetry
Available telemetry
Analyze and Monitor Telemetry with Power BI
2/6/2023 • 13 minutes to read • Edit Online

To make it simple to analyze Business Central telemetry, we've developed two Power BI apps available from
Microsoft AppSource. One app is for telemetry on environments. The other one is for telemetry on
apps/extensions (the telemetry defined in app.json). Both apps are free and open source but requires Power BI
pro licenses to use.

About the reports in the app


The app consists of four reports:
Usage
Errors
Performance
Administration
The usage report
The usage report provides a multi-perspective view into how Business central is being used. The report can have
data from in one or more environments or apps (depending on how you fill in the parameters and how you've
partitioned the Azure Application Insights resource).
What do the pages in the report show?
Sessions: See how sessions are distributed over a timeline, weekday, and time of day
Clients: See which types of clients and browsers that users use
Locations: See where users sign in from and which languages they use in the client
Page views: See which pages users use and when
Reports: See which reports users use and when
Feature usage: See which features users use and when
Integrations and Connectors: See the activity on system integrations (web service calls)
Deprecated features: check if online environments are using deprecated features such as basic authentication
and need to migrate to better solutions
Error report
The error report provides a multi-perspective view into errors occurring in one or more environments or apps
(depending on how you fill in the parameters and how you've partitioned the Azure Application Insights
resource). The report is a supplement to the Jupyter notebook trouble shooting guides (TSGs). Use the report to
investigate/slice'n'dice the data and the notebook to follow a prescribed path.
What do the pages in the report show?
User errors: When users get error dialogs, it can be a symptom of missing knowledge about the system, or
that some features aren't set up the way they're supposed to
Integrations errors: External systems communicate with Business Central using web services. Failures in this
area means that some of the integrations are probably not working correctly
System errors: Some Business Central modules or code might be misconfigured. Failures here indicate the
system isn't set up correctly.
Performance report
The performance report provides a multi-perspective view into the performance of one or more environments
or apps (depending on how you fill in the parameters and how you've partitioned the Azure Application Insights
resource). The report is a supplement to the Jupyter notebook trouble shooting guides (TSGs). Use the report to
investigate/slice'n'dice the data and the notebook to follow a prescribed path.
What do the pages in the report show?
Sessions: Statistics on sessions that were started, client types (UI clients, background, or web service), and
user types (normal, admin, or guest)
OnCompanyOpen: Timings of the OnCompanyOpen trigger (is run every time a session is created). Can
show if expensive code was added here
Page views: Timings of pages visited by users, client type that ran them (modern client or desktop), and
browsers used
Reports: Timings of reports, client type that ran them (UI clients or background), and reporting engine used
(Word, RDLC, or processing only)
Long Running SQL Queries: Insights into SQL queries that ran longer than 750 milliseconds, the extensions
and codeunits that called the database, and corresponding AL call stacks
Database lock timeouts: Insights into SQL queries that waited for a lock longer than 15 seconds, the
extensions and codeunits that called the database, and corresponding AL call stacks
Long Running AL methods: Insights into AL methods that ran longer than 10,000 milliseconds, the
extensions and codeunits they belong to, and corresponding AL call stacks
Incoming webservice calls/Outgoing webservice calls: Timings of incoming/outgoing web service calls and
their type (SOAP, OData, or API), http status codes, and the codeunit they expose
Job Queue/Task scheduler: Timings of background jobs/tasks
Configuration packages: Timings of configuration package operations
App Updates: Timings of how long time updates of installed apps take
Administration report
The Administration report provides a multi-perspective view into the current state of Business central
environments and any change done to them.
What do the pages in the report show?
Inventory: See an inventory of environments and their current version
Update Planning: See an overview of environment versions and their update schedules
All changes: See changes to environments, companies, extensions, and indexes
Environment Changes: See changes to environments (for example, stop/start, rename, copy, delete, update)
Company Changes: See changes to companies (for example, create, rename, and delete)
Extension Changes: See changes to extensions (for example, install, update, and uninstall)
Index Changes: See changes to indexes (keys) (added, removed)
Field Changes: See changes to fields that are tracked in the field monitoring feature. Consider monitoring
Business Central configuration tables to have that data show up here
Retention Policy: See date deleted due to retention policies set up in Business Central

Get the apps


App on Environment Telemetry
To install or update the app for environment telemetry, go to https://aka.ms/bctelemetryreport and select Get it
now .
You'll first have to sign in to Microsoft AppSource using your Power BI account name and password, if you aren't
already signed in. Follow the online instructions to get the app installed in Power BI.
Once installed, the Dynamics 365 Business Central Usage app appears under Apps in Power BI. A
workspace with the same name is also installed for configuring the app.

To open the app, from the navigation pane, select Apps > Dynamics 365 Business Central Usage .

By default, the app shows sample data in the reports. This sample data enables you to demo the app to
prospective customers without having to show data from existing customers.
App on App Telemetry
To install or update the app for app telemetry, go to https://aka.ms/bctelemetry-isv-app and select Get it now .
You'll first have to sign in to Microsoft AppSource using your Power BI account name and password, if you aren't
already signed in. Follow the online instructions to get the app installed in Power BI.
Once installed, the Dynamics 365 Business Central App Usage app appears under Apps in Power BI. A
workspace with the same name is also installed for configuring the app.
To open the app, from the navigation pane, select Apps > Dynamics 365 Business Central App Usage .
By default, the app shows sample data in the reports. This sample data enables you to demo the app to
prospective customers without having to show data from existing customers.

TIP
You can install the Power BI apps more than once. Just go to the install link for the app and select Get it now again.
When prompted, choose Install another copy of the app into a new workspace .

Connect to Azure Application Insights for the first time


After the app is installed, you can connect it to an Azure Application Insights resource to view actual data instead
of the sample data.
1. Get the Application Insights resource's application ID.
To connect the app to an Azure Application Insights resource, you'll need its Application ID. You can get
this ID from the Azure portal as follows:
a. Sign in to Azure portal.
b. Open the Application Insights resource, then select API Access .
c. In the API Access page, copy Application ID to the clipboard.
2. In Power BI, open the Dynamics 365 Business Central Usage app, the select Connect your data .

3. On the Connect to Dynamics 365 Business Central Usage page, fill in the Application Insights
application id with the ID you copied from the previous step. In the Lookback period box, select the
number of days back in time you want to show.
Other information on the page is optional. For more information, see Configure the app.
4. Select Next and wait while your credentials are checked.
5. Select Sign in and connect , then enter a valid name and password for accessing the Application
Insights resource, if asked.

NOTE
Keep the Authentication method set to OAuth2 . If you get the error The OAuth authentication method isn't
supported for this data source, check if the application ID is correct; that's usually the root cause for that error.

Configure an app after initial setup


Once an app is installed, you can use its workspace, such as Dynamics 365 Business Central Usage to
change the app configuration, for example, to connect to a different Application Insights resource or change how
many days back the data goes. Follow these steps:
1. From the navigation pane in the Power BI, select Workspaces > Dynamics 365 Business Central
Usage to open the workspace.
2. On the Dynamics 365 Business Central Usage page, next to Dataset , select More options (...) >
Settings .
3. On the Dataset page, go to Parameters and make your changes.
The app only has two required parameters needed for configuration:
Application Insights Application ID (controls where data is stored)
Lookback period (the number of days back in time you want to show)
Apart from required parameters, you can also control the following options:
Azure Active Directory (Azure AD) tenant mapping (define which customer names correspond to
which Azure AD tenant IDs). The format for this parameter is
{"map":[{ "AAD tenant id":"005bbe22-5949-4acb-9d24-3fb396c64a52" , "Domain":"Contoso 1" },{ "AAD
tenant id":"0140d8e7-ef60-4cc3-9a6b-b89042b3ea1f" , "Domain":"Contoso 2"}]}
Timezone (the Business Central platform emits telemetry in the UTC time zone. By setting a Timezone,
all visuals that show telemetry by hour of day will adjust to show data in the configured time zone).
Whether the app should refresh data (the default is every night around midnight); this option is
hidden under Advanced .
For the environment app, you can also define:
an include list of environments so that only data for these environments is loaded. The format for this
parameter is
{"include":[{"AAD tenant id":"<aad tenant id 1>","Name":"<environment name 1>"}, {"AAD tenant id":"
<aad tenant id 2>","Name":"<environment name 2>"}]}
4. When done making changes, you have to refresh the dataset to update the data shown in the app.
A quick way is to select Refresh now for the dataset on the workspace.
Or, you can schedule the refresh from the Settings page. For more information, see Configure scheduled
refresh.

NOTE
Once you connect to an Application Insights resource, You can't change the app back to show the sample data. If you
want to see the sample data, install the app again.

NOTE
If you turn off scheduled refresh and go back to the app, it will remove the Application ID and you have to enter it again.

Share the app with coworkers and others


Once installed, it's possible to share the app with coworkers and others (such as customers). You can:
Share the Power BI workspace with the person. The app will appear under Workspaces in their Power BI
portal.
Provide the URL to the person and ask them to open it in a browser. The app will appear under Apps in their
Power BI portal.
For more information, see Share Power BI reports and dashboards with coworkers and others

Use the app


Once installed and configured, how can you use the different reports in the app? We identified four different
personas as described in this table:

P ERSO N A DESC RIP T IO N

Account Manager Person making sales to new and existing customers.

Product Owner Person responsible for an extension/app.

Project manager Person responsible for the implementation of a Business


Central environment for a customer.
P ERSO N A DESC RIP T IO N

Supporter Person performing triage, investigation, and mitigation of


customer issues.

In the following table, you'll find examples of scenarios for each persona where the app might be of help.

P ERSO N A SC EN A RIO H O W T H E P O W ER B I A P P C A N H EL P

Account Manager Prospective customer has concerns The Power BI app comes with sample
that online solutions are a blackbox. data when you install it. If questions
pop up, show them what kind of
insights the app offers and that they
can get access to the app if they find it
useful. Focus on the Usage report
unless the customer wants to see
some of the more technical reports
(that is, Errors, Performance, or
Administration). If the customer has a
representative from IT, then show
them the Administration report.

Account Manager Plan new activities with an existing Most of the pages in the Usage report
customer. can help drive conversations with the
customer on how to get more value
from their Business Central
investment. For example, look at the
Page views, Reports, and Feature
Usage pages to check whether the
customer is using the functionality
they set out to when starting the
project. Lack of data typically means
lack of usage.

Account Manager Get existing customers excited about Go to the Usage report and open the
reporting with Excel layouts. Reports page to check whether the
customer is using the Excel layouts
(you can filter on the layout type). If
they are, then it's good. Maybe you
can follow up with training or PoCs on
Power Query and maybe also start
working differently with the customer
on reporting. With Excel layouts, some
reports only need a developer for the
AL report object, then the
customer/end users can do most/all of
the layout in Excel. If the customer isn't
using Excel layouts yet, show them the
power of Business Central reports with
Excel layouts and a bit of Power Query
in Excel.
P ERSO N A SC EN A RIO H O W T H E P O W ER B I A P P C A N H EL P

Product Owner Which features in our apps or per- Make sure that apps/extensions have
tenant extensions are being used and enabled telemetry in the app manifest
how often? (app.json). Use the Feature Telemetry
AL system module to equip your app
with usage telemetry. Consider having
separate Power BI apps for
apps/extensions and environments.
Once you have data in telemetry, then
go to the Usage report and visit the
pages Page views, 'Reports', and
Feature Usage. This gives you an
overview of the pages/reports/features
that users use in your app. You can
filter the results down to
publisher/app.

Project manager We need a way to track progress on Go to the Usage report and visit the
User Acceptance Testing (UAT) efforts Page views, Reports, and Feature
Usage pages to see what users are
doing in Business Central. Consider
sharing the app with the customer to
enable them to do the follow-ups
internally based on data.

Project manager We want a smooth go-live for the Use the Error dashboard in the Error
customer. report to drive errors to zero before
go-live. Monitor the dashboard in the
first weeks after go-live. Consider
sharing the app with the customer so
status meetings and follow-ups can be
based on data.

Project manager Business Central online only: We want Look at the Deprecated features page
to check if the customer will get in the Usage report to see if the
broken integrations when they get customer is still using web service keys
updated to version 20.0 or 21.0 (basic auth) for integrations. If you see
any data here, work with the customer
on a mitigation plan to move
integrations to OAuth.

Supporter Customer calls and says that Go to the Administration report, find
"something changed since Friday of the All changes page and filter to a
last week." period in time that overlaps with
"Friday of last week." There are various
changes that a customer can report,
such as data, UI, business logic,
performance, stability, and so on.
Depending on the reported change,
you might get lucky that one of the
lifecycle events for environments,
extensions, companies, or indexes can
explain the root cause of the changed
behavior. Otherwise, you can dig
further into the issue with the app
using KQL queries, or simply by
reaching out to the code owner.

Supporter Customer complains that some users Go to the Error report and investigate
can't sign in. the Login Errors page.
P ERSO N A SC EN A RIO H O W T H E P O W ER B I A P P C A N H EL P

Supporter Customer complains that users get Go to the Error report and investigate
lots of errors when using the system. the Error Dialogs, Permission Errors,
and Feature Errors pages. You can filter
pages by Extension Publisher to learn
which code path the error is coming
from.

Supporter Customer experiences many locking Use the Database Deadlocks page in
issues. the Error report to examine deadlocks.
Use the Database Lock Timeouts page
in the Performance report to examine
lock time-outs. Use the Long running
SQL queries page (filter SQL Statement
to "UPDLOCK") to investigate SQL
queries that take locks.

See also
Telemetry overview
Enabling telemetry
Available telemetry
Analyze Telemetry with KQL
Analyze and Monitor Telemetry with KQL
2/6/2023 • 2 minutes to read • Edit Online

Telemetry from Business Central is stored in Azure Application Insights in the tables traces and pageViews. The
language used to query data in Azure Application Insights is Kusto Query Language (KQL). This article has
information and links to resources to get started learning about the KQL language. As a simple example, follow
these steps:
1. In the Azure portal, open your Application Insights resource.
2. In the Monitoring menu, select Logs .
3. On the New Quer y tab, enter the following to get the last 100 traces:

traces
| where timestamp > ago(7d) // look back 7 days
| take 100 // only take 100 rows
| project timestamp, message, customDimensions // only choose these three columns
| sort by timestamp desc // show the most recent data first

Where can I use Kusto Queries?


You can use Kusto queries as the data source in many places. For example:
The logs part of Application Insights in the Azure portal
Power BI reports
Alerts
Azure Dashboards
Jupyter Notebooks (with the Kqlmagic extension)

Where can I learn more about KQL?


Here are some resources for you to get started on Kusto Query Language (KQL). Use CTRL+click to open them
in a new browser tab/window.
Kusto Query Language Overview
Kusto Query Language Tutorial
I know SQL. How do I do that in KQL?
Kusto Query Language (KQL) from Scratch (Pluralsight course, requires subscription)
Microsoft Azure Data Explorer - Advanced KQL (Pluralsight course, requires subscription)
How can I query multiple Application Insights resources from the same Kusto query? (blog post by Microsoft
MVP Stefano Demiliani)

Which tools can I use (KQL editors and clients)?


You can write and execute KQL in various tools. For example:
Kusto Explorer (desktop application). To learn how to connect, go to How to connect to Application Insights in
Kusto Explorer.
Azure Data Explorer. To learn how to connect, go to How to connect to Application Insights in Azure Data
Explorer.
In a Jupyter notebook hosted in Azure Data Studio
In a Jupyter notebook hosted in Visual Studio Code (with the Python and Jupyter Notebooks extensions
installed).
Application Insights portal (Under Logs in the Monitoring menu).
PowerShell (using the REST api). For an example, go to PowerShell samples.
About custom dimensions
Each event has a customDimensions column that includes a set of dimensions containing metrics specific to the
event. Each of these custom dimensions has a limit of 8000 characters. When logging an event with a dimension
exceeding 8000 characters, the Business Central Server adds more overflow dimension keys to the event to
contain the excess characters. There can be up to two extra overflow dimension keys, each with a maximum
8000 characters. The overflow dimension keys are named <dimension_key_name>_1 and <dimension_key_name>_2 ,
where <dimension_key> is the name of the original dimension key. So if the custom dimension key is
extensionCompilationDependencyList , then the overflow dimension keys would be
extensionCompilationDependencyList_1 and extensionCompilationDependencyList_2 .

NOTE
The 8000 character limit is governed by the Application Insights API.

See also
Telemetry overview
Enabling telemetry
Available telemetry
Analyze Telemetry with Power BI
Alert on Telemetry
2/6/2023 • 3 minutes to read • Edit Online

If something happens in your environment or app that you need to act on, you can set up a system that sends
you an alert. Azure Application Insights makes it easy to define such alerts.
You can use the following tools to define and set up alerts on telemetry events:
Azure Application Insights Alerts
Azure Logic Apps
Power Automate
All three approaches need a Kusto (KQL) query to define the alerting condition.

Define alerting condition queries


When defining an alert based on telemetry, you need to define two things:
1. A Kusto (KQL) query that defines the alerting condition. It's considered good practice to add a where clause
that limits the timestamp of events in the query, for example, | where timestamp > ago(1h) .
2. How often you want to run the alerting query. Typically, the recurrence follows the where clause in the
alerting query. For example, if the query looks back 1 hour, then you set your recurrence to 1 hour as well.

TIP
Samples of alerting queries are shared by Microsoft and third parties on the Business Central BCTech repository on
GitHub. You can also share your alerting queries with the community on GitHub.

Create alerts in Azure Application Insights


If you want to create alerts in Azure Application Insights, then do as follows:
1. Open the Azure portal and locate your Application Insights resource.
2. In the navigation pane on the left, select Aler ts .
3. Add a KQL alerting condition query in the condition for a custom log search.
To read more about Azure Monitor alerts, go to Azure Application Insights in the Azure documentation.

Create alerts using Azure Logic Apps and Power Automate


Azure Logic Apps and Power Automate have built-in connectors to query telemetry in Azure Application Insights
for setting up custom notifications or automating certain actions that are triggered by an environment's lifecycle
event.

NOTE
Samples of custom notifications and automations are shared by Microsoft and third parties on the Business Central
BCTech repository on GitHub. You can also share your Application Insights Alerts and Automations with the community
on GitHub.
The samples below can help getting started with customization and automation using Application Insights.

IMPORTANT
Deploying a Logic App to Azure also creates the API Connection Resources necessary to authenticate certain actions in
the Logic Apps.
After deploying the Logic App, navigate to the created API Connection Resources in the Azure Portal to authenticate
them. The Application Insights API Connection Resource can be authenticated using the Application ID and an API Key.
These can be found and generated on the API Access page of the Azure Application Insights resource in the Azure Portal.
If you have already have API Connection Resources deployed in the selected Resource Group for the connections needed
to run the Logic App you can reuse them by entering the same resource name before deploying the Logic App.

Example - Run an alerting query every "n" days and send an email
This Logic App runs every number of days (specified in app deployment). It lists all updates made available to
environments that emit telemetry to the specified Application Insights resource during the period.
Administrators can use this app to replace email notifications they'd receive for environments when set up as
notification recipient.

Example - Run an alerting query every "n" minutes and send a message to Teams
This Logic App queries Application Insights every number of minutes (specified in app deployment). It notifies a
user (also specified in deployment) of any deleted environments in Microsoft Teams. The action that sends the
notification in Teams can be updated to notify a Channel or Group Chat instead.

See also
Telemetry overview
Enabling telemetry
Available telemetry
Available telemetry areas
2/6/2023 • 3 minutes to read • Edit Online

In Application Insights, telemetry from Business Central is logged into the traces or pageview tables.
Currently, Business Central offers telemetry on the following operations:

EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

AppSource Provides See...


Submission information
Validation about validation
when an
extension is
submitted to
AppSource.

App key vault Provides [1] [1] See...


secrets information
about the
retrieval of
secrets from
Azure Key Vaults
by extensions.

Authorization Provides See...


information
about user sign-
in attempts.
Information
includes success
or failure
indication,
reason for
failure, user type,
and more.

Azure Function Provides See...


Integration[6] information
about requests
to Azure
Functions from
Business Central

Company Provides See...


lifecycle information
about creating,
copying, and
deleting of
companies.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Configuration Provides See...


package lifecycle information
about operations
done on
configuration
packages,
including
exporting,
importing,
applying, and
deleting.

Database Provides See...


deadlocks[5] information
about database
deadlocks that
occur.

Database lock Provides See...


timeouts information
about database
locks that have
timed out.

Database wait Provides See...


statistics information
about the wait
categories and
the wait times a
query runs into.

Email Provides See...


information
about the
success or failure
of sending
emails.

Environment Provides See...


lifecycle [5] information
about changes
and operations
on an
environment, like
updates,
hotfixes, copy,
move, delete,
configuration
changes,and
more.

Error message Provides See...


quality[5] information
about error
messages that
users thought
were helpful or
unhelpful.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Error method Provides See...


information
about error
dialogs that are
shown to the
users.

Extension Provides See...


lifecycle [2] information
about the
success or failure
of extension-
related
operations, like
publishing,
synchronizing,
installing, and
more.

Extension update Provides See...


information
about errors that
occur and
upgrade tags
used when
upgrading an
extension.

Feature Provides See...


telemetry information
about the usage
and errors of
features.

Field monitoring Provides See...


trace information
about the usage
of the field
monitoring
feature.

Job queue Provides See...


information
about creating
and running job
queue entries.

Long running AL Provides See...


method trace[3] information
about long
running AL
methods.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Long running Provides See...


operation (SQL information
query) about SQL
queries that take
longer than
expected to
execute.

Page views Provides [6] [4] See...


information
about the pages
that users open
in the modern
client.

Permissions Provides See...


information
about adding,
removing, and
assigning
permission sets.

Permissions Provides See...


dependency information
cycle[5] about
dependency
cycles in
permissions.

Permission Provides See...


error[5] information
about errors
related to
permissions that
users get.

Profile Provides See...


configuration information
lifecycle[6] about design
operations done
on profiles from
the client.

Report Provides See...


generation information
about the
execution of
reports.

Retention policy Provides See...


trace[3] information
about the usage
of the retention
policy feature.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Incoming web Provides See...


service requests information
about the
execution time of
incoming web
service requests.

Outgoing web Provides See...


service requests information
about the
execution time of
outgoing web
service requests.

Stopped Provides See...


sessions[5] information
about
background
sessions that
were forcibly
stopped from
the admin center
or by calling the
StopSession
method from AL.

Table index Provides See...


trace[3] information
about the
addition or
removal of a
table index.

Task scheduler Provides See...


lifecycle information the
execution of
scheduled tasks.

User checklists[5] Provides See...


information
about when the
status of a user
checklist changes

Verbose logging Provides See...


enabled/disabled information
[5] about when
additional
logging is
enabled and
disabled from
the client.
EXT EN SIO N M O RE
A REA DESC RIP T IO N O N L IN E O N - P REM ISES SUP P O RT IN F O RM AT IO N

Web service Provides See...


access key information
authentication about the
authentication of
web server
access keys on
web service
requests.

This signal is only emitted to the Application Insights resource that's specified in the extension.
2

Introduced in Business Central 2020 release wave 1, version 16.3. For extension telemetry, this signal was
introduced in 2020 release wave 2, version 17.1.
3

Introduced in Business Central 2020 release wave 1, version 17.1. For extension telemetry, this signal was
introduced in 2021 release wave 1, version 18.1.
4

Introduced in Business Central 2021 release wave 1, version 18.


5

Introduced in Business Central 2022 release wave 1, version 20.


6

Introduced in Business Central 2022 release wave 2, version 21.

See also
Telemetry Event IDs
Enable Sending Telemetry to Application Insights
Analyzing AppSource Submission Validation Trace
Telemetry
2/6/2023 • 10 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1, version 18.4, and later
When you submit an app to AppSource using Partner Center, it starts an automated validation process. This
technical validation process ensures the extensions in the app meet the technical requirements for going live. It
goes through many of the same checks described in technical validation.
If an app's set up for it, telemetry traces are emitted to and recorded in Application Insights. The data provides
details about the success or failure of different phases of the validation. For more information about setting up
telemetry for an app, see Sending Extension Telemetry to Azure Application Insights.

NOTE
In order to start analyzing your validation results, use this troubleshooting guide Dynamics 365 Business Central
Troubleshooting Guide (TSG) - AppSource Submission Results (SaaS).

Validation process overview


The validation process starts when you publish the app. The validation runs against each extension in the app,
for each country (market) specified for the offer in Partner Center, and for each Business Central version that the
submissions targets. For more information versions, see Against which releases of Business Central is your
submission validated?.
Extensions are validated using the AL compiler and the AppSourceCop code analyzer. Traces are emitted at
different phases during the process. Each submission is assigned a unique identifier (ID). This ID is included in
each trace for a submission, allowing you to query all trace related to the submission. The general flow for the
validation process is illustrated below:
1. AppSource submission validation request started
2. Validation diagnostic reported for information, warnings, or errors that occur on the submission
3. Version (X), country-region (X) validation started
4. Extension (X) validation started
5. Validation diagnostic reported for each error that occurs.
6. Extension (X) validation completed (successfully or with failures)
7. Repeat 3-5 for each extension in the submission
8. Version (X), country-region (X) validation completed (successfully or with failures)
9. Repeat 2-7 for other country-regions for the Business Central release (X)
10. Repeat 2-8 for other Business Central releases targeted by the submission
11. AppSource submission validation request completed (successfully or with failures)
To reduce the risk of failing the AppSource validation process, review the technical validation checklist before
you submit an app.

AppSource submission validation request started


Occurs when an app is published from Partner Center. For more information about publishing from Partner
Center, see Review and publish a Dynamics 365 offer - Validation and publishing steps.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message AppSource submission validation request star ted:


{validationRequestId}

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0028

countryRegions Lists the localized versions (markets) of the app that will be
validated, like US or DK .

extensions Specifies information about the extensions that are part of


the submission, which will be validated.

severity Information

versions Lists the Business Central release versions that the app will
be validated against, like 19.0 or 18.4

Common custom dimensions


The following table explains other custom dimensions that are common to all AppSource submission validation
traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

validationRequestId Specifies the unique identifier assigned to the app


submission validation process. All traces for the submission
validation will include this ID.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Diagnostic reported on AppSource submission validation request


Occurs during the submission validation request to report diagnostics related to the submission itself. For
example, it could be that a submission has duplicate apps, or it doesn't target any Business Central release. This
signal isn't necessarily an error, but can also be warning or information. This signal differs from other diagnostic
signals like LC0034 , which are reported during the compilation of one app for one country/release.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Diagnostic repor ted on AppSource submission


validation request: {validationRequestId}

severityLevel 1 for information, 2 for warning, 3 for error


Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0038

diagnosticCode Specifies the diagnostic identifier, like AS0001 or AL0001.

diagnosticMessage Specifies the diagnostic message.

diagnosticSeverity Info , Warning , or Error . Matches the severityLevel .

See common custom dimensions

(Version, country-region) validation started


Occurs when the validation has started for a specific version and country.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message (Version, countr y-region) validation star ted: version


{version}, countr y/region {countr yRegion}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0030

allExtensions Specifies information about the extensions that are part of


the submission and extensions that the submission
extensions depend on. Select the arrow to expand the
dimension to see the details about each extension.

baselineExtensions Specifies the previous versions of the extensions in the app


and the extensions they're dependent on. These extensions
form the baseline for validation if publishing a newer version
of an app that's already published.

extensions Specifies the extensions that are part of the submission and
will be validated. Select the arrow to expand the dimension
to see the details about each extension.

severity Information

version Specifies the Business Central release versions that the app
will be validated against, like 19.0 or 18.4 .

See common custom dimensions

Extension validation started


Occurs when the validation for a specific extension the submission has started.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension validation star ted: version {version},


countr y/region {countr yRegion} for extension
{extensionName} version {extensionVersion} by
{extensionPublisher} ({extensionId})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0032

countryRegion Specifies the localized version of the app that will be


validated.

extensionId Specifies the ID of the extension in the submission that will


be validated.

extensionName Specifies the name of the extension in the submission that


will be validated.

extensionPublisher Specifies the publisher of the extension in the submission


that will be validated.

extensionVersion Specifies the version of the extension in the submission that


will be validated.

severity Information

version Specifies the Business Central release that the extension will
be validated against, like 19.0 or 18.4 .

See common custom dimensions

Validation diagnostic reported


Occurs when an error occurs during the validation of an extension. The errors are reported by the AL compiler
or by the AppSourceCop analyzer.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Validation diagnostic repor ted: version {version},


countr y/region {countr yRegion} for extension
{extensionName} version {extensionVersion} by
{extensionPublisher} ({extensionId})

severityLevel 3
Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0034

countryRegion Specifies the localized version of the app that was validated.

diagnosticCode Specifies the diagnostic identifier, like AS0001 or AL0001.

diagnosticMessage Specifies the diagnostic error message.

diagnosticSeverity Error

diagnosticSourceLocation Specifies the location in the source code where the


diagnostic was reported. The format used is (Line,
Character).

diagnosticSourcePath Specifies the path to the file where the diagnostic was
reported.

extensionId Specifies the ID of the extension in the submission that will


be validated.

extensionName Specifies the name of the extension in the submission that


was validated.

extensionPublisher Specifies the publisher of the extension in the submission


that was validated.

extensionVersion Specifies the version of the extension in the submission that


was validated.

severity Error

version Specifies the Business Central release that the extension was
validated against, like 19.0 or 18.4 .

See common custom dimensions

Extension validation completed successfully


Occurs when the validation for a specific extension the submission has completed, and no errors occurred.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension validation completed successfully: version


{version}, countr y/region {countr yRegion} for
extension {extensionName} version
{extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 1
Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0033

countryRegion Specifies the localized version of the app that was validated.

extensionId Specifies the ID of the extension in the submission that will


be validated.

extensionName Specifies the name of the extension in the submission that


was validated.

extensionPublisher Specifies the publisher of the extension in the submission


that was validated.

extensionVersion Specifies the version of the extension in the submission that


was validated.

severity Information

version Specifies the Business Central release that the extension was
validated against, like 19.0 or 18.4 .

See common custom dimensions

Extension validation completed with failures


Occurs when the validation for a specific extension the submission has completed, but errors occurred.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension validation completed with failures: version


{version}, countr y-region {countr yRegion} for
extension {extensionName} version
{extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0037

countryRegion Specifies the localized version of the app that was validated.

extensionId Specifies the ID of the extension in the submission that will


be validated.
DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionName Specifies the name of the extension in the submission that


was validated.

extensionPublisher Specifies the publisher of the extension in the submission


that was validated.

extensionVersion Specifies the version of the extension in the submission that


was validated.

failureReason One or more error diagnostics were repor ted. For


more information about the diagnostics, see traces
with eventId LC0034.

severity Error

version Specifies the Business Central release that the extension was
validated against, like 19.0 or 18.4 .

See common custom dimensions

(Version, country-region) validation completed successfully


Occurs when the validation has completed for a specific version and country, and no errors occurred.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message (Version, countr y-region) validation completed


successfully: version {version}, countr y/region
{countr yRegion}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0031

allExtensions Specifies information about the extensions that were part of


the submission and extensions that the submission
extensions depend on. Select the arrow to expand the
dimension to see the details about each extension.

baselineExtensions Specifies the previous versions of the extensions in the app


and the extensions they're dependent on. These extensions
form the baseline for validation if publishing a newer version
of an app that's already published.

countryRegion Specifies the localized version of the app that was validated.
DIM EN SIO N DESC RIP T IO N O R VA L UE

extensions Specifies the extensions that were part of the submission


and were validated. Select the arrow to expand the
dimension to see the details about each extension.

severity Information

version Specifies the Business Central release that the app was
validated against, like 19.0 or 18.4 .

See common custom dimensions

(Version, country-region) validation completed with failures


Occurs when the validation has completed for a specific version and country, and errors occurred.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message (Version, countr y-region) validation completed with


failures: version {version}, countr y-region
{countr yRegion}

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0036

allExtensions Specifies information about the extensions that were part of


the submission and extensions that the submission
extensions depend on. Select the arrow to expand the
dimension to see the details about each extension.

baselineExtensions Specifies the previous versions of the extensions in the app


and the extensions they're dependent on. These extensions
form the baseline for validation if publishing a newer version
of an app that's already published.

countryRegion Specifies the localized version of the app that was validated.

extensions Specifies the extensions that were part of the submission


and were validated. Select the arrow to expand the
dimension to see the details about each extension.

failureReason One or more extension validation tasks have failed.

severity Error

version Specifies the Business Central release that the app was
validated against, like 19.0 or 18.4 .
DIM EN SIO N DESC RIP T IO N O R VA L UE

See common custom dimensions

AppSource submission validation request completed successfully


Occurs when the submission validation process has fully completed, and no errors occurred.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message AppSource submission validation request completed


successfully: {validationRequestId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0029

countryRegions Lists the localized versions (markets) of the app that were
validated, like US or DK .

extensions Specifies information about the extensions that were part of


the submission and validated.

severity Information

versions Lists the Business Central release that the app was validated
against, like 19.0 or 18.4 .

See common custom dimensions

AppSource submission validation request completed with failures


Occurs when the submission validation process has fully completed, but errors occurred.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message AppSource submission validation request completed


with failures: {validationRequestId}

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0035
DIM EN SIO N DESC RIP T IO N O R VA L UE

countryRegions Lists the localized versions (markets) of the app that were
validated, like US or DK .

extensions Specifies the extensions that were part of the submission


and validated.

failureReason One more extension validation tasks have failed.

severity Error

versions Lists the Business Central releases that the app was
validated against, like 19.0 or 18.4 .

See common custom dimensions

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Prepare a Configuration Package in the Business Central
Analyzing App Key Vault Secret Trace Telemetry
2/6/2023 • 6 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

App key vault telemetry gathers information about the acquisition of secrets in Azure Key Vaults by extensions
at runtime. For an overview of app key vaults and secrets, see Using App Key Vaults with Business Central
Extensions.
The app key vault secret process has two operations: initialization and retrieval. The telemetry data provides
information about the success or failure for each of these operations. There are various conditions that cause a
failure. The failure messages provide insight into the cause of the failure, helping you identify, troubleshoot, and
resolve issues.
Initialization
Initialization is the first stage. It verifies the configuration of the app key vault provider in the extension and on
the service. This stage is initiated by the TryInitializeFromCurrentApp method call in the extension code. Some
conditions that cause failures in this stage include:
The extension doesn't specify a key vault in it's app.json file.
The Azure Key Vault Client Identity settings are incorrect. For example, it could be that the application (client)
ID that you specified for the key vault reader application in Azure is wrong.
The Business Central Server lacks permission to the private key of the Azure Key Vault client certificate.
Retrieval
Retrieval is the second stage, and occurs after a successful initialization. In this stage, the service tries to get a
secret from a specified key vault. This stage is initiated by the GetSecret method call in the extension code.
Some conditions that cause failures include:
The secret name requested by the extension is doesn't exist or isn't valid.
The key vault doesn't exist.
The application ID doesn't have permission to read from the key vault.
For more information about using key vault secrets with extensions, see App Key Vaults with Business Central
Extensions.

App Key Vault secret initialization succeeded


Occurs when an extension secret was successfully initialized.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message App Key Vault initialization succeeded:


'{keyVaultUri}'.

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

alObjectId Specifies the ID of the AL object that was run by request.

alObjectName Specifies the name of the AL object that was run by request.

alObjectType Specifies the type of AL object that was run by request.

alStackTrace The stack trace in AL.

clientType Specifies the type of client that executed the request, such as
Background or Web . For a list of the client types, see
ClientType Option Type.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

eventId RT0014

extensionId Specifies the AppID of the extension that requested the


secret.

extensionName Specifies the name of the extension that requested the


secret.

extensionPublisher Specifies the publisher of the extension that requested the


secret.

extensionVersion Specifies the version of the extension that requested the


secret.

keyVaultUrls Specifies the DNS name of the Azure key vault that was used
in the request. The keyVaultUris are specified in the app.json
file of the extension.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

App Key Vault initialization failed


Occurs when a key vault failed to be initialized.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message App Key Vault initialization failed.


DIM EN SIO N DESC RIP T IO N O R VA L UE

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

alObjectId Specifies the ID of the AL object that was run by request.

alObjectName Specifies the name of the AL object that was run by request.

alObjectType Specifies the type of AL object that was run by request.

alStackTrace The stack trace in AL.

clientType Specifies the type of client that executed request, such as


Background or Web . For a list of the client types, see
ClientType Option Type.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

eventId RT0015

extensionId Specifies the AppID of the extension that requested the


secret.

extensionName Specifies the name of the extension that requested the


secret.

extensionPublisher Specifies the publisher of the extension that requested the


secret.

extensionVersion Specifies the version of the extension that requested the


secret.

failureReason Specifies the error that occurred.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

App Key Vault secret retrieval succeeded


Occurs when a secret used by an extension is successfully retrieved from an Azure Key Vault.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message App Key Vault secret retrieval succeeded from key


vault '{keyVaultUri}'.

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

alObjectId Specifies the ID of the AL object that was run by request.

alObjectName Specifies the name of the AL object that was run by request.

alObjectType Specifies the type of AL object that was run by request.

alStackTrace The stack trace in AL.

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

eventId RT0016

extensionId Specifies the AppID of the extension that requested the


secret.

extensionName Specifies the name of the extension that requested the


secret.

extensionPublisher Specifies the publisher of the extension that requested the


secret.

extensionVersion Specifies the version of the extension that requested the


secret.

keyVaultUrl Specifies the DNS name of the Azure key vault that was used
in the request. The keyVaultUris are specified in the app.json
file of the extension.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.
App Key Vault secret retrieval failed
Occurs when an extension failed to retrieve a secret from a specified Azure key vault.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message App Key Vault secret retrieval failed from key vault
'{keyVaultUri}'.

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

alObjectId Specifies the ID of the AL object that was run by request.

alObjectName Specifies the name of the AL object that was run by request.

alObjectType Specifies the type of AL object that was run by request.

alStackTrace The stack trace in AL.

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

eventId RT0017

extensionId Specifies the AppID of the extension that requested the


secret.

extensionName Specifies the name of the extension that requested the


secret.

extensionPublisher Specifies the publisher of the extension that requested the


secret.

extensionVersion Specifies the version of the extension that requested the


secret.
DIM EN SIO N DESC RIP T IO N O R VA L UE

keyVaultUrl Specifies the DNS name of the Azure key vault that was used
in the request. The keyVaultUris are specified in the app.json
file of the extension.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

See also
App Key Vaults with Business Central Extensions
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Authorization Trace Telemetry
2/6/2023 • 11 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

Authorization telemetry provides information about the authorization of users (or services) when trying to sign
in to Business Central. This telemetry data can help you identify problems a user (or a service) might experience
when signing in.
Authorization signals are emitted in two stages of sign-in. The first stage is the initial authorization, before the
CompanyOpen trigger is run. In this stage, the system verifies that the user account is enabled in the tenant and
has the correct entitlements. The telemetry data includes:
Success or failure of the sign-in attempt
Reason for failure
Type of user (such as normal, administrator, or delegated user)
Whether the user belongs to the tenant or is an invited user
The next stage occurs after a successful authorization attempt, when trying to open the company (that is, when
the CompanyOpen trigger run). The telemetry data indicates whether the company opened successfully or failed
(for some reason).

NOTE
Business Central 2020 release wave 1, version 16.1, introduces changes to some operation_Name and message
dimension values. The differences from earlier versions are indicated in the following sections.

AuthorizationSucceeded(PreOpenCompany)
Occurs when a user has been successfully authorized. This data is not emitted for on-premises environments.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Version 16.1 and later:


Authorization Succeeded (Pre Open Company)

Before Version 16.1:


Authorization steps prior to the open company
trigger succeeded.

operation_Name Authorization Succeeded (Pre Open Company)

Note: The use of the operation_Name column was


deprecated in version 16.1. In future versions, data won't be
stored in this column. So in version 16.1 and later, use the
custom dimension column eventID column custom in
Kusto queries instead of operation_Name .

severityLevel 1
Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

authorizationStatus Succeeded

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

entitlementSetIds Specifies the entitlements that the user has in Business


Central.

eventId RT0003

guestUser true indicates that the user is a guest user on the tenant.
false indicates the user belongs to the tenant.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

userType Specifies whether the user is a Delegated_admin ,


Internal_Admin , or Normal user . See UserType.

UserType
VA L UE DESC RIP T IO N SEE M O RE

Delegated_admin Indicates that the user is a delegated Delegated Administrator Access to


administrator on the tenant. Delegated Business Central Online
administrators are typically reserved
for partners. Delegated administrator Customers delegate administration
privileges are granted to users by the privileges to partners
customer. You grant these privileges by
setting up a Partner Relationship in the
Microsoft Partner Center.

Internal_Admin Indicates that the user is an internal Administration as an internal


administrator on the tenant. As an administrator in Business Central
internal administrator, the user is
assigned the Global admin role in Assign admin roles in Microsoft 365
the Microsoft 365 admin center. admin center

Normal user Indicates that the user is a normal user Create Users According to Licenses
in the tenant, based on the license.
NOTE
The client type is not known when the server emits the pre-open company events (RT0001 and RT0003). You need to join
to data for the events RT0002/RT0004 if you need both userType and clientType.

AuthorizationFailed(PreOpenCompany)
Occurs when a user sign-in has failed authorization. This data is not emitted for on-premises environments.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Version 16.1 and later (depending on the cause):


Authorization Failed (Pre Open Company): User
is disabled.
Authorization Failed (Pre Open Company): User
has no entitlements.
User has no access
User is not a member of the environment's
security group
Before Version 16.1:
Authorization steps prior to the open company
trigger failed, see failureReason column for details.

operation_Name Authorization Failed (Pre Open Company)

Note: The use of the operation_Name column was


deprecated in version 16.1. In future versions, data won't be
stored in this column. So in version 16.1 and later, use the
custom dimension column eventID column custom in
Kusto queries instead of operation_Name .

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

authorizationStatus Failed

failureReason Specifies why the sign-in failed. See Troubleshooting failures


section for details.

guestUser true indicates that the user is a guest user on the tenant.
false indicates the user belongs to the tenant.

eventId RT0001

userType Specifies whether the user is a Delegated_admin ,


Internal_Admin , or Normal user . See UserType.

Troubleshooting (PreOpen Company) authorization failures


The user was successfully authenticated in Azure Active Directory but the user account is disabled in Business
Central.
This message occurs when the user's account is valid, but the account is disabled. If you open the user account in
Business Central, you'll see the State field is set to Disabled .
Resolution
Enable the user account by setting the State field to Enabled . For more information, see Create Users
According to Licenses.
A user successfully authenticated in Azure Active Directory but the user does not have any entitlements in
Business Central.
This message occurs if the user has an account, but the account hasn't been assigned any entitlements.
Entitlements are part of the license. Entitlements are permissions that describe which objects in Business Central
a user can use, according to their Azure Active Directory role or license. For an explanation of entitlements, see
Business Central entitlements explained
Resolution
Entitlements are assigned to the user account in the Microsoft 365 admin center or Microsoft Partner Center.
They aren't assigned in Business Central. To assign entitlements to a user, see one of the following articles:
From Microsoft 365 admin center, see Add users individually or in bulk to Microsoft 365.
From the Microsoft Partner Center, see User management tasks for customer accounts.
The user is not a direct/indirect member of the security group associated with the environment, or the group
does not exist, hence restricting the user access to the environment
In Azure Active Directory (Azure AD), you can create security that include users that you want to give access to
your environments. Then, from the Business Central Admin center, you can associate the groups with your
environments. This error occurs if the user who tries to sign in isn't a member of the security group, or the
security group assigned to the environment doesn't exist in Azure AD. For more information, see Managing
Production and Sandbox Environments in the Admin Center.

Authorization Succeeded (Open Company)


Occurs when the company has opened successfully. This data is emitted both for online and on-premises
environments.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Version 16.1 and later:


Authorization Succeeded (Open Company)

Before version 16.1:


Authorization steps in the open company trigger
succeeded.

operation_Name Authorization Succeeded (Open Company)

Note: The use of the operation_Name column was


deprecated in version 16.1. In future versions, data won't be
stored in this column. So in version 16.1 and later, use the
custom dimension column eventID column custom in
Kusto queries instead of operation_Name .
DIM EN SIO N DESC RIP T IO N O R VA L UE

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

authorizationStatus Success

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

clientType Specifies the type of client that opened the session, such as
Background or Web . For a list of the client types, see
ClientType Option Type.

companyName Specifies the display name of the Business Central company


for which the report was run.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId RT0004

result Success

serverExecutionTime Specifies the amount of time it took the server to open the
company. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the report


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements**.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time it took to open the company**.


The time has the format hh:mm:ss.sssssss.

** From telemetrySchemaVersion 0.6 and onwards, this value also includes the CompanyOpen operation.

Authorization Failed (Open Company)


Occurs when a company has failed to open. This data is emitted both for online and on-premises environments.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Version 16.1 and later (depending on the cause):


Authorization Failed (Open Company): Invalid
company name.
Authorization Failed (Open Company): User
has no permission to company.
Authorization Failed (Open Company): The
tenant is locked.
Authorization Failed (Open Company): The
license has expired or the trial period has
ended.
Authorization Failed (Open Company): The
user's license is not valid for use on
production companies.
Authorization Failed (Open Company): Error in
OnOpenCompany trigger
Before version 16.1:
Authorization steps in the open company trigger
failed, see failureReason column for details.

operation_Name Authorization Failed (Open Company)

Note: The use of the operation_Name column was


deprecated in version 16.1. In future versions, data won't be
stored in this column. So in version 16.1 and later, use the
custom dimension column eventID column custom in
Kusto queries instead of operation_Name .

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

authorizationStatus Failed

companyName Specifies the name of the company that the user tried to
open.

failureReason Specifies why the sign-in failed. See Troubleshooting failures


section for details.

eventId RT0002

Troubleshooting (Open Company) authorization failures


The company name is not valid, because the name is either empty or exceeds the maximum allowed length.
This message occurs when a user tries to sign in to a company whose name exceeds the maximum allowed
length.
Resolution
This message typically occurs when a user tries to access a specific company in Business Center by entering a
URL in the browser address, for example,
https://businesscentral.dynamics.com/?company=CRONUS%20International%20Ltd. . If the name exceeds 30
characters, then this message occurs. Make sure that the user has the proper name of the company.
The user does not have permission to access the company.
This message occurs when a user account in Business Central doesn't have the proper permissions to the
company.
Resolution
In Business Central, open the user account and modify the permissions the user to give them access to the
company. For more information, see Assign Permissions to Users and Groups.

TIP
A good starting point is to look at the Effective Permissions that the user has on the company. You can do this from
the user card by selecting Effective Permissions and setting the Company to the company in question.

The company doesn't exist.


This message occurs when a user tries to sign in to a company, but the company isn't found in Business Central.
Resolution
This message typically occurs when a user tries to access a specific company in Business Center by entering a
URL in the browser address, for example,
https://businesscentral.dynamics.com/?company=CRONUS%20International%20Ltd. . Make sure that the user has the
proper name of the company.
User cannot open the company because the tenant is locked.
This message indicates that the tenant has been locked by Microsoft, typically for security reasons like
preventing repeated malicious sign-in attempts. The tenant isn't accessible by any user.
Resolution
For help with resolving this issue, read the following articles or contact Microsoft Support:
Troubleshoot account lockout problems with an Azure AD Domain Services managed domain
"It looks like your account has been blocked" error when signing in to Microsoft 365
The user can't sign in to the company because the assigned license has expired or the trial period has ended.
This message occurs for one the following reasons:
The license being used has expired.
The license was trial license and the trial period has ended. Trial licenses are typically assigned when
customers subscribe for an evaluation version by using self-service sign-up (also known as IW or viral sign-
up). This license has a time limit.
Resolution
Renew the existing license or obtain a new license. Licenses are purchased through the Cloud Solution Provider
(CSP) program. For more information, see the Cloud Service Provider site and the Microsoft Dynamics 365
Business Central Licensing Guide.
You can't open the company, because it is a production company. Your license isn't valid for use on production
companies.
This message occurs because the license doesn't allow the user to open production companies. For example, the
user may be using a trial license that is only valid on the evaluation version.
Resolution
Obtain a license that can be used on production companies. Licenses are purchased through the Cloud Solution
Provider (CSP) program. For more information, see the Cloud Service Provider site and the Microsoft Dynamics
365 Business Central Licensing Guide.
Error in OnOpenCompany trigger
This message occurs when AL code causes an error during the OnOpenCompany trigger or event.
Resolution
Because AL code can trigger any type of error, the resolution will depend on the executed AL code. See the
failureReason dimension for a callstack to determine where the error occurred.

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Company Lifecycle Trace Telemetry
2/6/2023 • 11 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1, version 16.1


Company lifecycle telemetry gathers data about the success or failure of the following company-related
operations:
creating a company
copying a company
deleting a company
Failed operations result in a trace log entry that includes a reason for the failure.

Company created
Occurs when the company has been successfully created.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Company created: {companyName}

{companyName} indicates the name of the new company.

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company.

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId LC0001

result Success

serverExecutionTime Specifies the amount of time it took the server to create the
company. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that were executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time it took to create the company.


The time has the format hh:mm:ss.sssssss.

Company creation canceled


Occurs when creating a company was canceled.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Company creation canceled: {companyName}

{companyName} indicates the name of the company being


created.

severityLevel 2

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company.


DIM EN SIO N DESC RIP T IO N O R VA L UE

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId LC0002

failureReason Operation was canceled

result Failure

serverExecutionTime Specifies the amount of time it took the server create the
company before being canceled. The time has the format
hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that were executed


by the operation.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time used to create the company


before being canceled. The time has the format
hh:mm:ss.sssssss.

Company creation failed


Occurs when a company failed to be created.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Company creation failed: {companyName}

{companyName} indicates the name of the company being


created.

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId LC0003

failureReason Specifies the exception that indicates the cause of the failure.

result Failure

serverExecutionTime Specifies the amount of time it took the server create the
company before it failed. The time has the format
hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that were executed


by the operation.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time used to create the company


before it failed. The time has the format hh:mm:ss.sssssss.

Company copied
Occurs when a company has been copied from another company successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Company copied: {companyNameSource} to


{companyNameDestination}
{companyNameSource} is name of the company that
was copied.
{companyNameDestination} is the name of new
company that was created.

severityLevel 2

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyNameDestination Specifies the name of the new company.

companyNameSource Specifies the name of the Business Central company.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId LC0004

result Success

serverExecutionTime Specifies the amount of time it took the server to copy the
company. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that were executed


by the operation.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.
DIM EN SIO N DESC RIP T IO N O R VA L UE

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time it took to copy the company.


The time has the format hh:mm:ss.sssssss.

Company copy canceled


Occurs when a copying a company was canceled.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Company copied canceled: {source company name}


to {destination company name}
{companyNameSource} is name of the company that
was being copied.
{companyNameDestination} is the name of new
company that was being created.

severityLevel 2

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

clientType Specifies the type of client that executed operation, such as


Background or Web . For a list of the client types, see
ClientType Option Type.

companyName Specifies the display name of the Business Central company.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId LC0005

failureReason Operation was canceled .

result Failure
DIM EN SIO N DESC RIP T IO N O R VA L UE

serverExecutionTime Specifies the amount of time it took the server to copy the
company. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that were executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time used to do the operation. The


time has the format hh:mm:ss.sssssss.

Company copy failed


Occurs when a company failed to be copied from another company.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Company copy failed: {companyNameSource} to


{companyNameDestination}
{companyNameSource} is name of the company that
was being copied.
{companyNameDestination} is the name of new
company that was being created.

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0006

failureReason Specifies the exception that indicates the cause of the failure.

result Failure

serverExecutionTime Specifies the amount of time on the server. The time has the
format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that were executed.

sqlRowsRead Specifies the number of table rows that by the SQL


statements.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time used to create the company


before it failed. The time has the format hh:mm:ss.sssssss.

Company deleted
Occurs when a company has been deleted successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Company deleted: {companyName}

{companyName} indicates the name of the company that


was deleted.

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId LC0007

result Success

serverExecutionTime Specifies the amount of time it took on server. The time has
the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the operation


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time it took to delete the company.


The time has the format hh:mm:ss.sssssss.

Company deletion canceled


Occurs when deleting a company failed was canceled.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Company deletion canceled: {companyName}

{companyName} indicates the name of the company that


was being deleted.

severityLevel 2

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company.

component Dynamics 365 Business Central Ser ver .


DIM EN SIO N DESC RIP T IO N O R VA L UE

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId LC0008

failureReason Operation was canceled

result Failure

serverExecutionTime Specifies the amount of time it took on server. The time has
the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that executed by


the operation.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time used to delete the company


before being canceled. The time has the format
hh:mm:ss.sssssss.

Company deletion failed


Occurs when a company failed to be deleted.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Company deletion failed: {companyName}

{companyName} indicates the name of the company that


was being deleted.

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .
DIM EN SIO N DESC RIP T IO N O R VA L UE

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId LC0009

failureReason Specifies the exception that caused the failure.

result Failed

serverExecutionTime Specifies the amount of time it took on server. The time has
the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that executed by


the operation.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time used to delete the company


before it failed. The time has the format hh:mm:ss.sssssss.

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Configuration Package Telemetry
2/6/2023 • 3 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2, version 17.2, and later
Configuration package telemetry gathers data about the following operations on configuration packages:
Export
Import
Apply
Delete
For information about working with configuration packages, see Prepare a Configuration Package in the
Business Central Application Help.

Common custom dimensions


The following table explains custom dimensions that are common to all configuration package traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alCategory RapidStar t

alDataClassification SystemMetadata

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type. Added in version 20.0.

companyName The name of the company where the operation is applied.


Added in version 20.0.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Configuration package export started


Occurs when an export operation on a configuration package is started.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Configuration package expor t star ted:


{alPackageCode}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E3F

alExecutionId Specifies the ID of the export operation.

alPackageCode Specifies the ID of the configuration package being exported.

Configuration package exported successfully


Occurs when an export operation on a configuration package completes successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Configuration package expor ted successfully:


{alPackageCode}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E3G

alExecutionId Specifies the ID of the export operation.

alExecutionTimeInMs Specifies the number of milliseconds it took to complete the


export operation.

alPackageCode Specifies the ID of the configuration package that was


exported.

See common custom dimensions

Configuration package import started


Occurs when an import operation on a configuration package is started.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Configuration package impor t star ted:


{alPackageCode}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E3H

alExecutionId Specifies the ID of the import operation.

alPackageCode Specifies the ID of the configuration package being


imported.

See common custom dimensions

Configuration package imported successfully


Occurs when an import operation on a configuration package completes successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Configuration package impor ted successfully:


{alPackageCode}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E3I

alExecutionTimeInMs Specifies the number of milliseconds it took to complete the


import operation.

alExecutionId Specifies the ID of the import operation.

alPackageCode Specifies the ID of the configuration package that was


imported.

See common custom dimensions

Configuration package apply started


Occurs when an apply operation on a configuration package is started.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Configuration package apply star ted:


{alPackageCode}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E3N

alExecutionId Specifies the ID of the apply operation.

alPackageCode Specifies the ID of the configuration package being applied.

See common custom dimensions

Configuration package applied successfully


Occurs when an apply operation on a configuration package completes successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Configuration package applied successfully:


{alPackageCode}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E3O

alExecutionId Specifies the ID of the apply operation.

alExecutionTimeInMs Specifies the number of milliseconds it took to complete the


apply operation.

alErrorCount Specifies the number of errors that occurred when applying


the configuration package.

alFieldCount Specifies the number of fields that were included in the


migration table of the applied configuration package.

alPackageCode Specifies the ID of the configuration package that was


applied.

alRecordCount Specifies the number of records that were included in the


applied configuration package.
DIM EN SIO N DESC RIP T IO N O R VA L UE

See common custom dimensions

Configuration package deleted successfully


Occurs when a configuration package is deleted successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Configuration package deleted successfully:


{alPackageCode}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E3P

alPackageCode Specifies the ID of the configuration package that was


deleted.

See common custom dimensions

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Prepare a Configuration Package in the Business Central
Analyzing Database Deadlock Telemetry
2/6/2023 • 2 minutes to read • Edit Online

INTRODUCED IN: Business Central 2022 release wave 1, version 20.0


The database deadlock telemetry gathers information about deadlocks that happen. Deadlocks can prevent
users from completing tasks in the Business Central client. A deadlock occurs when two or more processes block
each other because each has locked a database resource. The system terminates and rolls back one of the
sessions (known as the deadlock victim), then emits a telemetry signal.
As a partner or developer, this telemetry provides several benefits:
Makes you aware that there are deadlocks happening.
Let's you identify who was the victim in deadlock situations.
In some deadlock problems, the process that is the victim and the process that succeeds will change by
chance. In these cases, both will be stored in the telemetry resource as different deadlock events.
For further monitoring and troubleshooting, this telemetry is complimented by other features like:
Enable SQL database deadlock monitoring on a sandbox or on-premises environment. For more
information, see Monitoring SQL Database Deadlocks.
Database lock trace telemetry. For more information, see Database lock trace telemetry.

IMPORTANT
For Business Central on-premises, you must turn on the EnableDeadlockMonitoring setting of the Business Central Server
instance to collect the telemetry. For more information, see Configuring Business Central Server.

Database deadlock occurred


Occurs when a deadlock occurs.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Database deadlock occurred

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId RT0028

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alObjectId Specifies the ID of the AL object that ran the transaction that
was victim of the deadlock.
DIM EN SIO N DESC RIP T IO N O R VA L UE

alObjectName Specifies the name of the AL object that ran the transaction
that was victim of the deadlock.

alObjectName Specifies the name of the AL object that ran the transaction
that victim of the deadlock.

alObjectType Specifies the type of the AL object that ran the transaction
that was victim of the deadlock, such as a page or report.

alStackTrace The stack trace in AL.

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company.

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

extensionId Specifies the AppID of the extension that was involved in the
deadlock.

extensionName Specifies the name of the extension that was involved in the
deadlock.

extensionVersion Specifies the version of that was involved in the deadlock.

sessionId Specifies the ID of the session that was involved by the


deadlock.

sqlServerSessionId Specifies the ID of the SQL server session that was the victim
of the deadlock.

sqlStatement Specifies the SQL statement that was the victim of in the
deadlock.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

See also
Monitoring and Analyzing Telemetry
Database Lock Timeout Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Database Lock Timeout Trace Telemetry
2/6/2023 • 5 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1, version 16.0


Database lock timeout telemetry gathers information about database locks that have timed out. The telemetry
data allows you to troubleshoot what caused these locks.
In the client, when a lock has timed out, the user is presented with a message, similar to the following message:
The operation could not complete because a record in the [table name] table was locked by another user. Please
retry the activity.
Two types of trace events are emitted to Application Insights:
The first is a Database lock timed out event. This event includes general information about the lock
request. This event includes information like the AL object and code that is impacted by the lock, the
extension involved, and more.
The Database lock timed out event then triggers one or more Database lock snapshot events.
Database lock snapshot events provide details about SQL sessions that hold database locks at the time
of lock timeout, including the session that caused the lock timeout. These events include specific details
about the SQL lock request on the database, like the type, status, mode, and the table.

NOTE
In later versions of Business Central on-premises, the Business Central Server includes the
EnableLockTimeoutMonitoring setting. Use this setting to turn database lock timeout telemetry on or off. By default, it
is off. For more information, see Configuring Business Central Server.

TIP
When analyzing database lock timeout telemetry, it's useful to look at combined data from the Database lock timed
out event and Database lock snapshot events. You can combine data from different events by using joins in your
Kusto queries. For an example, see LockTimeouts.kql in the Microsoft/BCTech repository on GitHub. For more general
information about using joins, see Joins in Azure Monitor log queries in the Microsoft Azure documentation.

Database lock timed out


Occurs when a database lock has timed out.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Database lock timed out

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alExecutingMethodScope Specifies the AL action that is running the transaction that


caused the lock.

alObjectId Specifies the ID of the running AL object that requested the


lock.

alObjectName Specifies the name of the running AL object that requested


the lock. not shown

alObjectType Specifies the type of the running AL object that requested


the lock, such as a page or report.

alStackTrace The stack trace in AL.

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company.

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

eventId RT0012

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

extensionId Specifies the AppID of the extension that was involved in the
lock.

extensionName Specifies the name of the extension that was involved in the
lock.

extensionVersion Specifies the version of that was involved in the lock.

sessionId Specifies the ID of the session that requested the lock.


DIM EN SIO N DESC RIP T IO N O R VA L UE

snapshotId Specifies the ID of the database snapshot. This ID is used to


identify associated Database lock snapshot trace events.

sqlServerSessionId Specifies the ID of the SQL server session that requested the
lock.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Database lock snapshot


Occurs when a database lock has timed out. Each Database lock snapshot trace event is associated with a
specific Database lock timed out trace event.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Database lock snapshot: {snapshotId}

The value of the {snapshotId} maps to the snapshotId


dimension of the Database lock timed out trace event
that triggered this event.

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alExecutingMethodScope Specifies the AL action that is running the transaction that


caused the lock.

alObjectId Specifies the ID of the running AL object that requested the


lock.

alObjectName Specifies the name of the running AL object that requested


the lock.

alObjectType Specifies the type of the running AL object that requested


the lock, such as a page or report.

alStackTrace The stack trace in AL.

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)
DIM EN SIO N DESC RIP T IO N O R VA L UE

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

eventId RT0013

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

extensionId Specifies the AppID of the extension that was involved in the
lock.

extensionName Specifies the name of the extension that was involved in the
lock.

extensionVersion Specifies the version of that was involved in the lock.

sessionId Specifies the ID of the session that requested the lock.

snapshotId Specifies the ID of the database snapshot. All messages in


the snapshot share this ID.

sqlLockRequestMode Specifies the lock mode that determines how concurrent


transactions can access the resource. For more information,
see Lock Modes.

sqlLockRequestStatus Specifies the current status of the lock, which can be one of
the following values:
CNVRT - means that the lock is transitioning from
another mode, but the conversion is blocked by
another process that holds a lock with a conflicting
mode.
GRANT - means that the lock is active.
WAIT - means that the lock is blocked by another
process that holds a lock with a conflicting mode.

sqlLockResourceType Specifies the database resource affected by the lock. For


example, DATABASE , FILE , OBJECT , PAGE , KEY , and
more.

sqlServerSessionId Specifies the ID of the SQL server session that requested the
lock.

sqlTableName Specifies the name of table on which the lock was held.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.
See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Database Wait Statistics Telemetry
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 1, version 20.0, and later
The database performance can also be analyzed by checking the information at Database Wait Statistics . You
can see how many queries got delayed because of different wait types along with their wait times. The wait
types give you an idea about the resources or operations that are responsible for the slow performance.
For more information about wait statistics in optimizing database and application performance, see Database
Wait Statistics in Dynamics 365 Business Central.

NOTE
The wait times aren't live. These statistics show the wait times for the queries which are completed from the time the
database was started or when it was reset.

Database wait statistics snapshot taken


Occurs when you choose the Emit Telemetr y icon on the Database Wait Statistics view in the client.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Database wait statistics snapshot taken:


{snapshotId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId RT0025

snapshotId Specifies the ID given to the snapshot.

Common custom dimensions


The following table explains custom dimensions that are common to all database wait statistic traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

component Dynamics 365 Business Central Ser ver .


DIM EN SIO N DESC RIP T IO N O R VA L UE

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Database wait statistics snapshot entry


Occurs when a query has to wait because of a resource, queue, or external event in the client. It's the snapshot
entry for each wait category.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Database wait statistics snapshot entr y:


{databaseWaitStatisticsCategor y}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId RT0026

snapshotId Specifies the ID given to the snapshot.

databaseMaxWaitTimeInMs Specifies the maximum wait time in milliseconds for a specific


wait category.

databaseSignalWaitTimeInMs Specifies the time difference between when the query was
signaled to wait and when it starts to process.

databaseStartedDuration Specifies the date and time when the database was started.

databaseWaitingTasksCount Specifies the total number of waits for a wait category.

databaseWaitStatisticsCategory Specifies which type of wait a query is experiencing.

databaseWaitTimeInMs Specifies the total wait time for a wait category including the
databaseSignalWaitTimeInMs.

See common custom dimensions

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Performance for Developers
How to work with a performance problem
Analyzing Email Trace Telemetry
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2, update 17.2, and later
Email telemetry gathers data about the following operations:
An email was sent successfully
An attempt to send an email failed
Before you can collect this data, you'll have to set up email. For more information, see Set Up Email in the
Business Central application help.

Email sent successfully


Occurs when an email was successfully sent from the client.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Email sent successfully

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alCategory Email

alConnector Specifies the email-provider connector used to send the


email. Possible values include:
Current User
Microsoft 365
SMTP
Other custom connectors installed by extensions.
The connector is specified on the email accounts that are set
up in Business Central. For more information, see Adding
Email Accounts.

alDataClassification SystemMetadata

alEmailMessageID Specifies the GUID assigned to email, like C7A56676-9F3F-


4044-90F0-D7F3196AC366.

alObjectId 8888 , which is the ID of the system application codeunit


that sends emails.
DIM EN SIO N DESC RIP T IO N O R VA L UE

alObjectName Email Dispatcher , which is the name of the system


application codeunit that sends the emails.

alObjectType CodeUnit

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentName Specifies the name of the tenant environment. See


Managing Environments. This dimension isn't included for
Business Central on-premises environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId AL0000CTV

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Failed to send email


Occurs when an email failed to be sent from the client.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Failed to send email.

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alCategory Email

alConnector Specifies the email-provider connector used to send the


email. Possible values include:
Current User
Microsoft 365
SMTP
Other custom connectors installed by extensions.
The connector is specified on the email accounts that are set
up in Business Central. For more information, see Adding
Email Accounts.
DIM EN SIO N DESC RIP T IO N O R VA L UE

alDataClassification SystemMetadata

alEmailMessageID Specifies the GUID assigned to email, like C7A56676-9F3F-


4044-90F0-D7F3196AC366.

alErrorCallStack Specifies the AL callstack when the error occurred. This


dimension was added in version 19.0.

alErrorText Specifies the AL error message. This dimension was added in


version 19.0.

alObjectId 8888 , which is the ID of the system application codeunit


that sends emails.

alObjectName Email Dispatcher , which is the name of the system


application codeunit that sends the emails.

alObjectType CodeUnit

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentName Specifies the name of the tenant environment. See


Managing Environments. This dimension isn't included for
Business Central on-premises environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId AL0000CTP

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

TIP
You can also view failed emails in the Email Outbox page in the Business Central client.

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Environment Lifecycle Trace Telemetry
2/6/2023 • 64 minutes to read • Edit Online

APPLIES TO: Business Central online

Environment lifecycle telemetry gathers data about the success or failure of the following environment-related
operations:
Update an environment
Start/stop/restart an environment
Copy an environment
Point-in-time restore an environment
Move an environment to a difference Azure Active Directory (AAD) tenant
Cancel a session from the Business Central admin center
Export the environment database
Change the environment configuration
Delete an environment
Rename an environment
Telemetry is also gathered on the following data update events:
Data upgrade started
Data upgrade succeeded
Data upgrade failed
Data upgrade recovery succeeded
Data upgrade recovery failed
Failed operations result in a trace log entry that includes a reason for the failure.
Custom dimensions available in all events
The following dimensions are available in all events described below and aren't included in the individual event
documentation:

DIM EN SIO N DESC RIP T IO N O R VA L UE

component Dynamics 365 Business Central Control Plane

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Environment update available for scheduling


Occurs when a new update is available for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment update available for scheduling:


{environmentName} to version {destinationVersion}

{environmentName} indicates the name of the


environment.

{destinationVersion} indicates the new version that is


available.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationVersion Specifies the version we are updating to.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0100

registeredForUpdateOnOrAfterDateUtc Specifies the date and time (shown in UTC), registered in the
Business Central admin center, from which an update can be
scheduled.

sourceVersion Specifies the version we are updating from.

updatePeriodEndDateUtc Specifies the end date and time of the update period (shown
in UTC).

updatePeriodStartDateUtc Specifies the start date and time of the update period
(shown in UTC).

Environment update scheduled


Occurs when the environment is scheduled to be updated.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment update scheduled: {environmentName}


to version {destinationVersion}, update on or after
date: {registeredForUpdateOnOrAfterDateUtc}

{environmentName} indicates the name of the


environment.

{destinationVersion} indicates the new version that is


available.

{registeredForUpdateOnOrAfterDateUtc} indicates the


date and time that is registered as the beginning of the
update window in the admin center.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

canPartnerReschedule A boolean value (true or false) that specifies whether a


partner can reschedule the update in the Business Central
admin center. Set to true if the partner can reschedule the
update.

destinationVersion Specifies the version we are updating to.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0101

ignoreUpdateWindow A boolean value (true or false) that specifies whether to


ignore the update window. Set to true if the update window
was ignored by the Business Central update service.

registeredForUpdateOnOrAfterDateUtc Specifies the date and time (shown in UTC), registered in the
Business Central admin center, from which an update can be
scheduled.

sourceVersion Specifies the version we are updating from.


DIM EN SIO N DESC RIP T IO N O R VA L UE

updateDateSelectedByPartner Boolean value (True or False). Set to True if the update date
was chosen by the partner in the admin center.

updatePeriodEndDateUtc Specifies the end date and time of the update period (shown
in UTC).

updatePeriodStartDateUtc Specifies the start date and time of the update period
(shown in UTC).

updateWindowEndTimeUtc Specifies the end date and time of the update window
(shown in UTC).

updateWindowStartTimeUtc Specifies the start date and time of the update window
(shown in UTC).

Environment update missed


Occurs when the environment was scheduled to be updated, but it wasn't possible to start the update in the
update window defined in the admin center.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment update missed: {environmentName} to


version {destinationVersion}

{environmentName} indicates the name of the


environment.

{destinationVersion} indicates the new version that is


available.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationVersion Specifies the version we are updating to.

environmentName Specifies the name of the tenant environment. See


Managing Environments.
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0102

ignoreUpdateWindow A boolean value (true or false) that specifies whether to


ignore the update window. Set to true if the update window
was ignored by the Business Central update service.

registeredForUpdateOnOrAfterDateUtc Specifies the date and time (shown in UTC), registered in the
Business Central admin center, from which an update can be
scheduled.

sourceVersion Specifies the version we are updating from.

updatePeriodEndDateUtc Specifies the end date and time of the update period (shown
in UTC).

updatePeriodStartDateUtc Specifies the start date and time of the update period
(shown in UTC).

updateWindowEndTimeUtc Specifies the end date and time of the update window
(shown in UTC).

updateWindowStartTimeUtc Specifies the start date and time of the update window
(shown in UTC).

Environment update postponed


Occurs when updates for version that the environment is on has been set on hold.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment update postponed: {environmentName}


to version {destinationVersion}

{environmentName} indicates the name of the


environment.

{destinationVersion} indicates the new version that is


available.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .
DIM EN SIO N DESC RIP T IO N O R VA L UE

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationVersion Specifies the version we are updating to.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0103

sourceVersion Specifies the version we are updating from.

Environment update resumed


Occurs when an update for a version that the environment is running on has been started again after being
stopped.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment update resumed: {environmentName}


to version {destinationVersion}

{environmentName} indicates the name of the


environment.

{destinationVersion} indicates the new version that is


available.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .
DIM EN SIO N DESC RIP T IO N O R VA L UE

destinationVersion Specifies the version we are updating to.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0104

ignoreUpdateWindow A boolean value (true or false) that specifies whether to


ignore the update window. Set to true if the update window
was ignored by the Business Central update service.

registeredForUpdateOnOrAfterDateUtc Specifies the date and time (shown in UTC), registered in the
Business Central admin center, from which an update can be
scheduled.

sourceVersion Specifies the version we are updating from.

updatePeriodEndDateUtc Specifies the end date and time of the update period (shown
in UTC).

updatePeriodStartDateUtc Specifies the start date and time of the update period
(shown in UTC).

updateWindowEndTimeUtc Specifies the end date and time of the update window
(shown in UTC).

updateWindowStartTimeUtc Specifies the start date and time of the update window
(shown in UTC).

Environment update started


Occurs when the update was started for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment update star ted: {environmentName} to


version {destinationVersion}

{environmentName} indicates the name of the


environment.

{destinationVersion} indicates the new version that is


available.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationVersion Specifies the version we are updating to.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0105

ignoreUpdateWindow A boolean value (true or false) that specifies whether to


ignore the update window. Set to true if the update window
was ignored by the Business Central update service.

initiatedFrom Specifies where the operation was initiated from, such as


TenantAdminCenter .

registeredForUpdateOnOrAfterDateUtc Specifies the date and time (shown in UTC), registered in the
Business Central admin center, from which an update can be
scheduled.

remainingTimeInUpdateWindow The time from the start of the operation until the end of the
registered update window.

sourceVersion Specifies the version we are updating from.

updatePeriodEndDateUtc Specifies the end date and time of the update period (shown
in UTC).

updatePeriodStartDateUtc Specifies the start date and time of the update period
(shown in UTC).

updateWindowEndTimeUtc Specifies the end date and time of the update window
(shown in UTC).

updateWindowStartTimeUtc Specifies the start date and time of the update window
(shown in UTC).

Environment updated successfully


Occurs when the environment was successfully updated.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment updated successfully:


{environmentName} to version {destinationVersion}

{environmentName} indicates the name of the


environment.

{destinationVersion} indicates the new version that is


available.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationVersion Specifies the version we are updating to.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0106

ignoreUpdateWindow A boolean value (true or false) that specifies whether to


ignore the update window. Set to true if the update window
was ignored by the Business Central update service.

initiatedFrom Specifies where the operation was initiated from, such as


TenantAdminCenter .

registeredForUpdateOnOrAfterDateUtc Specifies the date and time (shown in UTC), registered in the
Business Central admin center, from which an update can be
scheduled.

sourceVersion Specifies the version we are updating from.

totalTime Specifies the total time the operation ran for.


DIM EN SIO N DESC RIP T IO N O R VA L UE

updatePeriodEndDateUtc Specifies the end date and time of the update period (shown
in UTC).

updatePeriodStartDateUtc Specifies the start date and time of the update period
(shown in UTC).

updateWindowEndTimeUtc Specifies the end date and time of the update window
(shown in UTC).

updateWindowStartTimeUtc Specifies the start date and time of the update window
(shown in UTC).

Environment failed to update


Occurs when the update for the environment failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment failed to update: {environmentName}


to version {destinationVersion}

{environmentName} indicates the name of the


environment.

{destinationVersion} indicates the new version that is


available.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationVersion Specifies the version we are updating to.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.


DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0107

failureCode Specifies code that describes the type of error that blocks
the update, such as PteCompilation .

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

ignoreUpdateWindow A boolean value (true or false) that specifies whether to


ignore the update window. Set to true if the update window
was ignored by the Business Central update service.

initiatedFrom Specifies where the operation was initiated from, such as


TenantAdminCenter .

registeredForUpdateOnOrAfterDateUtc Specifies the date and time (shown in UTC), registered in the
Business Central admin center, from which an update can be
scheduled.

recovered A boolean value (true or false) that specifies whether the


environment was recovered to its state before the upgrade
attempt. Set to true if the environment was recovered.

sourceVersion Specifies the version we are updating from.

totalTime Specifies the total time the operation ran for.

updatePeriodEndDateUtc Specifies the end date and time of the update period (shown
in UTC).

updatePeriodStartDateUtc Specifies the start date and time of the update period
(shown in UTC).

updateWindowEndTimeUtc Specifies the end date and time of the update window
(shown in UTC).

updateWindowStartTimeUtc Specifies the start date and time of the update window
(shown in UTC).

Environment restart operation initiated


Occurs when a restart operation has been initiated from the admin center.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment restar t operation initiated:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0110

Environment restarted successfully


Occurs when a restart operation succeeded for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment restar ted successfully:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0111

totalTime Specifies the total time the operation ran for.

Environment restart operation failed


Occurs when a restart operation failed for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment restar t operation failed:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0112

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

totalTime Specifies the total time the operation ran for.


Environment start operation initiated
Occurs when a start operation has been initiated for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment star t operation initiated:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0113

Environment started successfully


Occurs when a restart operation succeeded for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment star ted successfully:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0114

totalTime Specifies the total time the operation ran for.

Environment start operation failed


Occurs when a start operation failed for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment star t operation failed:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0115

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

totalTime Specifies the total time the operation ran for.

Environment stop operation initiated


Occurs when a stop operation has been initiated for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment stop operation initiated:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0116

Environment stopped successfully


Occurs when a stop operation succeeded for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment stopped successfully:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0117

totalTime Specifies the total time the operation ran for.

Environment stop operation failed


Occurs when a stop operation failed for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment stop operation failed:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0118

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

totalTime Specifies the total time the operation ran for.

Environment copy operation started on source


Occurs when a copy operation for the environment started on the source environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment copy operation star ted on source:


{environmentName} to
{destinationEnvironmentName}

{environmentName} indicates the name of the


environment.

{destinationEnvironmentName} indicates the name of the


destination environment

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .
DIM EN SIO N DESC RIP T IO N O R VA L UE

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationEnvironmentName Specifies the name of the destination environment of the


operation.

destinationEnvironmentType Specifies the type of the destination environment of the


operation.

destinationEnvironmentVersion Specifies the version of the destination environment of the


operation.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0119

Environment copied successfully


Occurs when a copy operation for the environment succeeded.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment copied successfully:


{environmentName} to
{destinationEnvironmentName}

{environmentName} indicates the name of the


environment.

{destinationEnvironmentName} indicates the name of the


destination environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .
DIM EN SIO N DESC RIP T IO N O R VA L UE

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationEnvironmentName Specifies the name of the destination environment of the


operation.

destinationEnvironmentType Specifies the type of the destination environment of the


operation.

destinationEnvironmentVersion Specifies the version of the destination environment of the


operation.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0120

totalTime Specifies the total time the operation ran for.

Environment copy operation failed on source


Occurs when a copy operation for the environment failed on the source environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment copy operation failed on source:


{environmentName} to
{destinationEnvironmentName}

{environmentName} indicates the name of the


environment.

{destinationEnvironmentName} indicates the name of the


destination environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .
DIM EN SIO N DESC RIP T IO N O R VA L UE

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationEnvironmentName Specifies the name of the destination environment of the


operation.

destinationEnvironmentType Specifies the type of the destination environment of the


operation.

destinationEnvironmentVersion Specifies the version of the destination environment of the


operation.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0121

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

totalTime Specifies the total time the operation ran for.

Environment copy operation started on destination


Occurs when a copy operation for the environment started on the destination environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment copy operation star ted on destination:


{environmentName} from {sourceEnvironmentName}

{environmentName} indicates the name of the


environment.

{sourceEnvironmentName} indicates the name of the


environment that was to be copied.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0122

sourceEnvironmentName Specifies the name of the source environment of the


operation.

sourceEnvironmentType Specifies the type of the source environment of the


operation.

sourceEnvironmentVersion Specifies the version of the source environment of the


operation.

Environment copied successfully to destination


Occurs when a copy operation for the environment succeeded on the destination environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment copied successfully to destination:


{environmentName} from {sourceEnvironmentName}

{environmentName} indicates the name of the


environment.

{sourceEnvironmentName} indicates the name of the


environment that was to be copied.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .
DIM EN SIO N DESC RIP T IO N O R VA L UE

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0123

sourceEnvironmentName Specifies the name of the source environment of the


operation.

sourceEnvironmentType Specifies the type of the source environment of the


operation.

sourceEnvironmentVersion Specifies the version of the source environment of the


operation.

totalTime Specifies the total time the operation ran for.

Environment copy operation failed on destination


Occurs when a copy operation for the environment failed on the destination environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment copy operation failed on destination:


{environmentName} from {sourceEnvironmentName}

{environmentName} indicates the name of the


environment.

{sourceEnvironmentName} indicates the name of the


environment that was to be copied.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .
DIM EN SIO N DESC RIP T IO N O R VA L UE

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0124

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

sourceEnvironmentName Specifies the name of the source environment of the


operation.

sourceEnvironmentType Specifies the type of the source environment of the


operation.

sourceEnvironmentVersion Specifies the version of the source environment of the


operation.

totalTime Specifies the total time the operation ran for.

Environment point-in-time restore operation started on source


Occurs when a point-in-time restore operation for the environment started on the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment point-in-time restore operation star ted


on source: {environmentName} to
{destinationEnvironmentName}

{environmentName} indicates the name of the


environment.

{destinationEnvironmentName} indicates the name of the


destination environment for the operation.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationEnvironmentName Specifies the name of the destination environment of the


operation.

destinationEnvironmentType Specifies the type of the destination environment of the


operation.

destinationEnvironmentVersion Specifies the version of the destination environment of the


operation.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0125

pointInTimeUtc Specifies the point in time (in UTC) to which the environment
should be restored to.

Environment point-in-time restored successfully


Occurs when a point-in-time restore operation for the environment completed successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment point-in-time restored successfully:


{environmentName} to
{destinationEnvironmentName}

{environmentName} indicates the name of the


environment.

{destinationEnvironmentName} indicates the name of the


destination environment for the operation.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationEnvironmentName Specifies the name of the destination environment of the


operation.

destinationEnvironmentType Specifies the type of the destination environment of the


operation.

destinationEnvironmentVersion Specifies the version of the destination environment of the


operation.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0126

pointInTimeUtc Specifies the point in time (in UTC) to which the environment
should be restored to.

totalTime Specifies the total time the operation ran for.

Environment point-in-time restore operation failed on source


Occurs when a point-in-time restore operation for the environment failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment point-in-time restore operation failed


on source: {environmentName} to
{destinationEnvironmentName}

{environmentName} indicates the name of the


environment.

{destinationEnvironmentName} indicates the name of the


destination environment for the operation.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

destinationEnvironmentName Specifies the name of the destination environment of the


operation.

destinationEnvironmentType Specifies the type of the destination environment of the


operation.

destinationEnvironmentVersion Specifies the version of the destination environment of the


operation.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0127

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

pointInTimeUtc Specifies the point in time (in UTC) to which the environment
should be restored to.

totalTime Specifies the total time the operation ran for.

Environment point-in-time restore operation started on destination


Occurs when a point-in-time restore operation for the environment started on the destination environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment point-in-time restore operation star ted


on destination: {environmentName} from
{sourceEnvironmentName}

{environmentName} indicates the name of the


environment.

{sourceEnvironmentName} indicates the name of the


source environment for the operation.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

eventId LC0128

pointInTimeUtc Specifies the point in time (in UTC) to which the environment
should be restored to.

sourceEnvironmentName Specifies the name of the source environment of the


operation.

sourceEnvironmentType Specifies the type of the source environment of the


operation.

sourceEnvironmentVersion Specifies the version of the source environment of the


operation.

Environment point-in-time restored successfully to destination


Occurs when a point-in-time restore operation for the environment completed successfully on the destination
environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment point-in-time restored successfully to


destination: {environmentName} from
{sourceEnvironmentName}

{environmentName} indicates the name of the


environment.

{sourceEnvironmentName} indicates the name of the


source environment for the operation.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0129

pointInTimeUtc Specifies the point in time (in UTC) to which the environment
should be restored to.

sourceEnvironmentName Specifies the name of the source environment of the


operation.

sourceEnvironmentType Specifies the type of the source environment of the


operation.

sourceEnvironmentVersion Specifies the version of the source environment of the


operation.

totalTime Specifies the total time the operation ran for.

Environment point-in-time restore operation failed on destination


Occurs when a point-in-time restore operation for the environment failed in the destination environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment point-in-time restore operation failed


on destination: {environmentName} to
{sourceEnvironmentName}

{environmentName} indicates the name of the


environment.

{sourceEnvironmentName} indicates the name of the


source environment for the operation.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0130

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

pointInTimeUtc Specifies the point in time (in UTC) to which the environment
should be restored to.

sourceEnvironmentName Specifies the name of the source environment of the


operation.

sourceEnvironmentType Specifies the type of the source environment of the


operation.

sourceEnvironmentVersion Specifies the version of the source environment of the


operation.

totalTime Specifies the total time the operation ran for.

Environment move to different AAD tenant operation scheduled


Occurs when the environment is scheduled to be moved to a different Azure Active Directory (AAD) tenant.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment move to {destinationAadTenantId} AAD


tenant operation scheduled to run at
{registeredForMoveDateUtc}:
{sourceEnvironmentName}

{sourceEnvironmentName} indicates the name of the


environment to be moved.

{destinationAadTenantId} indicates the AAD tenant that


the environment should be moved to.

{registeredForMoveDateUtc} indicates the date and time


that have been registered for the move.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

destinationAadTenantId Specifies the destination Azure Active Directory (AAD) tenant


ID for the move.

destinationEnvironmentName Specifies the name of the destination environment of the


operation.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0131

registeredForMoveDateUtc Specifies the date and time (in UTC) registered by Microsoft
Support on which the operation should happen.

sourceEnvironmentName Specifies the name of the source environment of the


operation.

sourceAadTenantId Specifies the source Azure Active Directory (AAD) tenant ID


for the move.

Environment move to different AAD tenant operation scheduling


failed
Occurs when the operation to schedule a move of an environment to a different Azure Active Directory (AAD)
tenant failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment move to {destinationAadTenantId} AAD


tenant operation scheduling failed:
{sourceEnvironmentName}

{sourceEnvironmentName} indicates the name of the


environment to be moved.

{destinationAadTenantId} indicates the AAD tenant that


the environment should be moved to.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

destinationAadTenantId Specifies the destination Azure Active Directory (AAD) tenant


ID for the move.

destinationEnvironmentName Specifies the name of the destination environment of the


operation.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0132

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

registeredForMoveDateUtc Specifies the date and time (in UTC) registered by Microsoft
Support on which the operation should happen.

sourceEnvironmentName Specifies the name of the source environment of the


operation.

sourceAadTenantId Specifies the source Azure Active Directory (AAD) tenant ID


for the move.

totalTime Specifies the total time the operation ran for.

Environment move to different AAD tenant operation started


Occurs when the operation to move the environment to a different AAD tenant started.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment move to {destinationAadTenantId} AAD


tenant operation operation star ted:
{sourceEnvironmentName}

{sourceEnvironmentName} indicates the name of the


environment to be moved.

{destinationAadTenantId} indicates the AAD tenant that


the environment should be moved to.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

destinationAadTenantId Specifies the destination Azure Active Directory (AAD) tenant


ID for the move.

destinationEnvironmentName Specifies the name of the destination environment of the


operation.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0133

sourceEnvironmentName Specifies the name of the source environment of the


operation.

sourceAadTenantId Specifies the source Azure Active Directory (AAD) tenant ID


for the move.

Environment moved successfully to different AAD tenant


Occurs when the operation to move the environment to a different AAD tenant completed successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment moved to {destinationAadTenantId}


AAD tenant successfully: {sourceEnvironmentName}

{sourceEnvironmentName} indicates the name of the


environment that was moved.

{destinationAadTenantId} indicates the AAD tenant that


the environment was moved to.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

destinationAadTenantId Specifies the destination Azure Active Directory (AAD) tenant


ID for the move.

destinationEnvironmentName Specifies the name of the destination environment of the


operation.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0134

sourceEnvironmentName Specifies the name of the source environment of the


operation.

sourceAadTenantId Specifies the source Azure Active Directory (AAD) tenant ID


for the move.

totalTime Specifies the total time the operation ran for.

Environment move to different AAD tenant failed


Occurs when the operation to move the environment to a different AAD tenant failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment move to {destinationAadTenantId} AAD


tenant operation failed: {sourceEnvironmentName}

{sourceEnvironmentName} indicates the name of the


environment that was to be moved.

{destinationAadTenantId} indicates the AAD tenant that


the environment was to be moved to.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

destinationAadTenantId Specifies the destination Azure Active Directory (AAD) tenant


ID for the move.
DIM EN SIO N DESC RIP T IO N O R VA L UE

destinationEnvironmentName Specifies the name of the destination environment of the


operation.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0135

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

sourceEnvironmentName Specifies the name of the source environment of the


operation.

sourceAadTenantId Specifies the source Azure Active Directory (AAD) tenant ID


for the move.

totalTime Specifies the total time the operation ran for.

Environment session cancellation started


Occurs when a session is requested to be cancelled from the admin center.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment session {sessionId} cancellation


star ted: {environmentName}

{environmentName} indicates the name of the


environment.

{sessionId} indicates the id of the session that is being


cancelled.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0136

sessionId Specifies the ID of the session being cancelled.

Environment session cancelled successfully


Occurs when a session was successfully cancelled from the admin center.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment session {sessionId} cancelled


successfully: {environmentName}

{environmentName} indicates the name of the


environment.

{sessionId} indicates the id of the session that is being


cancelled.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0137
DIM EN SIO N DESC RIP T IO N O R VA L UE

sessionId Specifies the ID of the session being cancelled.

totalTime Specifies the total time the operation ran for.

Environment session cancellation failed


Occurs when a session cancellation request from the admin center failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment session {sessionId} cancellation failed:


{environmentName}

{environmentName} indicates the name of the


environment.

{sessionId} indicates the id of the session that is being


cancelled.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0138

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

sessionId Specifies the ID of the session being cancelled.

totalTime Specifies the total time the operation ran for.


Environment database export operation started
Occurs when a database export is requested from the admin center.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment database expor t operation star ted:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

blobUrl Specifies the URL of the blob where the database export file
will be saved.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0139

Environment database exported successfully


Occurs when the environment database was successfully exported from the admin center.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment database expor ted successfully:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

blobUrl Specifies the URL of the blob where the database export file
will be saved.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0140

totalTime Specifies the total time the operation ran for.

Environment database export operation failed


Occurs when a database export request from the admin center failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment database expor t operation failed:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

blobUrl Specifies the URL of the blob where the database export file
will be saved.
DIM EN SIO N DESC RIP T IO N O R VA L UE

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0141

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

totalTime Specifies the total time the operation ran for.

Environment configuration key updated


Occurs when a configuration key for the environment was successfully updated.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment configuration key


{environmentConfigurationKey} updated for
environment {environmentName} to value:
{newValue}

{environmentName} indicates the name of the


environment.

{environmentConfigurationKey} indicates the name of


the configuration key to be updated.

{newValue} indicates the new value of the key.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentConfigurationKey Specifies an environment configuration key, such as


ApplicationInsightsKey .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0142

newValue Specifies the value of the key after the operation.

oldValue Specifies the value of the key before the operation.

Environment configuration key failed to update


Occurs when a configuration key for the environment failed to be updated.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment configuration key


{environmentConfigurationKey} failed to update for
environment {environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentConfigurationKey Specifies an environment configuration key, such as


ApplicationInsightsKey .

environmentName Specifies the name of the tenant environment. See


Managing Environments.
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0143

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

newValue [ The value that the operation was supposed to update to

oldValue Specifies the value of the key before the operation.

totalTime Specifies the total time the operation ran for.

Environment configuration key deleted


Occurs when a configuration key for the environment was successfully deleted.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment configuration key


{environmentConfigurationKey} deleted for
environment {environmentName}

{environmentName} indicates the name of the


environment.

{environmentConfigurationKey} indicates the name of


the configuration key to be updated.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentConfigurationKey Specifies an environment configuration key, such as


ApplicationInsightsKey .

environmentName Specifies the name of the tenant environment. See


Managing Environments.
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0144

oldValue Specifies the value of the key before the operation.

Environment configuration key failed to be deleted


Occurs when a configuration key for the environment failed to be deleted.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment configuration key


{environmentConfigurationKey} failed to delete for
environment {environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentConfigurationKey Specifies an environment configuration key, such as


ApplicationInsightsKey .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0145
DIM EN SIO N DESC RIP T IO N O R VA L UE

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

oldValue Specifies the value of the key before the operation.

totalTime Specifies the total time the operation ran for.

Environment update window modified


Occurs when the update window for the environment was successfully updated.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment update window was modified for


environment: {environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0146

newUpdateWindowStartTimeUtc The start time (in UTC) for the new update window.

newUpdateWindowEndTimeUtc The end time (in UTC) for the new update window.

oldUpdateWindowStartTimeUtc The start time (in UTC) for the old update window.

oldUpdateWindowEndTimeUtc The end time (in UTC) for the old update window.
Environment update window modification failed
Occurs when a update window failed to be updated.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment update window modification failed for


environment: {environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0147

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

newUpdateWindowStartTimeUtc The start time (in UTC) for the new update window.

newUpdateWindowEndTimeUtc The end time (in UTC) for the new update window.

oldUpdateWindowStartTimeUtc The start time (in UTC) for the old update window.

oldUpdateWindowEndTimeUtc The end time (in UTC) for the old update window.

totalTime Specifies the total time the operation ran for.

Environment delete operation started


Occurs when a delete operation was started for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment delete operation star ted:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

deletionReason Specifies the reason for the delete operation

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0149

Environment deleted
Occurs when the environment was successfully deleted.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment deleted successfully:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

deletionReason Specifies the reason for the delete operation

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0150

totalTime Specifies the total time the operation ran for.

Environment delete operation failed


Occurs when a delete operation for the environment failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment delete operation failed:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .
DIM EN SIO N DESC RIP T IO N O R VA L UE

deletionReason Specifies the reason for the delete operation

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0151

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

totalTime Specifies the total time the operation ran for.

Environment rename operation started


Occurs when a rename operation was started for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment rename operation star ted:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.


DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0152

newEnvironmentName Specifies the new name of the environment.

Environment renamed
Occurs when the environment was successfully renamed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment renamed successfully:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0153

newEnvironmentName Specifies the new name of the environment.

totalTime Specifies the total time the operation ran for.

Environment rename operation failed


Occurs when a rename operation for the environment failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment rename operation failed:


{environmentName}

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0154

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

newEnvironmentName Specifies the new name of the environment.

totalTime Specifies the total time the operation ran for.

Environment app hotfix scheduled by App Management API


Occurs when an app hotfix for the environment has been scheduled by the App Management API service.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app '{extensionName}' hotfix to version


{extensionDestinationVersion} scheduled for
environment: {environmentName}

{extensionName} indicates the name of the extension/app


to be hotfixed.

{extensionDestinationVersion} indicates the new


version for the app that is available.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0155

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionSourceVersion Specifies the current version of the extension/app.


DIM EN SIO N DESC RIP T IO N O R VA L UE

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

Environment app hotfix scheduling by App Management API failed


Occurs when an app hotfix for the environment could not be scheduled by the App Management API service.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app '{extensionName}' hotfix to version


{extensionDestinationVersion} scheduling failed for
environment: {environmentName}

{extensionName} indicates the name of the extension/app


to be hotfixed.

{extensionDestinationVersion} indicates the version of


the app that the hotfix should update it to.

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0156

extensionId Specifies the ID of the extension/app.


DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionSourceVersion Specifies the current version of the extension/app.

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

totalTime Specifies the total time the operation ran for.

Environment app hotfix cancelled by App Management API


Occurs when an app hotfix for the environment was cancelled by the App Management API service.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app '{extensionName}' hotfix to version


{extensionDestinationVersion} was cancelled for
environment: {environmentName}

{extensionName} indicates the name of the extension/app


to be hotfixed.

{extensionDestinationVersion} indicates the new


version for the app that is available.

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0157

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionSourceVersion Specifies the current version of the extension/app.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

Environment app hotfix started by App Management API


Occurs when an app hotfix for the environment was started by the App Management API service.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app '{extensionName}' hotfix to version


{extensionDestinationVersion} star ted for
environment: {environmentName}

{extensionName} indicates the name of the extension/app


to be hotfixed.

{extensionDestinationVersion} indicates the new


version for the app that is available.

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0158

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionSourceVersion Specifies the current version of the extension/app.


DIM EN SIO N DESC RIP T IO N O R VA L UE

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

Environment app hotfix applied successfully by App Management API


Occurs when an app hotfix for the environment applied successfully by the App Management API service.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app '{extensionName}' hotfix to version


{extensionDestinationVersion} applied successfully
for environment: {environmentName}

{extensionName} indicates the name of the extension/app


to be hotfixed.

{extensionDestinationVersion} indicates the new


version for the app that is available.

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0159
DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionSourceVersion Specifies the current version of the extension/app.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

totalTime Specifies the total time the operation ran for.

Environment app hotfix operation by App Management API failed


Occurs when an app hotfix for the environment was applied by the App Management API service and failed to
be installed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app '{extensionName}' hotfix to version


{extensionDestinationVersion} failed for
environment: {environmentName}

{extensionName} indicates the name of the extension/app


to be hotfixed.

{extensionDestinationVersion} indicates the new


version for the app that is available.

{environmentName} indicates the name of the


environment.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0160

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionSourceVersion Specifies the current version of the extension/app.

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

totalTime Specifies the total time the operation ran for.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

Environment data upgrade operation started


Occurs when a data upgrade operation on an environment is started.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment data upgrade operation star ted:


{environmentName}

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0175

Environment data upgrade operation completed successfully


Occurs when a data upgrade operation on an environment has compeleted successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment data upgrade operation completed


successfully: {environmentName}

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

environmentName Specifies the name of the tenant environment. See


Managing Environments.
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0176

totalTime Specifies the total time the operation ran for.

Environment data upgrade operation failed


Occurs when a data upgrade operation on an environment has failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment data upgrade operation failed:


{environmentName}

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0177

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

totalTime Specifies the total time the operation ran for.

Recovery from a failed data upgrade operation has completed


successfully
Occurs when recovery operation that's run after a failed data upgrade operation has completed successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Recover y from a failed data upgrade operation has


completed successfully: {environmentName}

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0178

totalTime Specifies the total time the operation ran for.

Recovery from a failed data upgrade operation has failed


Occurs when recovery operation that's run after a failed data upgrade operation has also failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Recover y from a failed data upgrade operation has


failed: {environmentName}

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

environmentName Specifies the name of the tenant environment. See


Managing Environments.
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

environmentVersion Specifies the version of the tenant environment.

eventId LC0179

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

totalTime Specifies the total time the operation ran for.

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Error Message Quality Telemetry
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: > APPLIES TO: Business Central 2022 release wave 1 and later
When a user gets an error message while working in the application, the message includes a yes or no question
as to whether the message was helpful, similar to the following illustration:

If a user selects either Yes or No , a signal is emitted and recorded in Application Insights. This information can
help partners and developers get insight into error messages that users find hard to understand. They can then
follow up with the customer to help out.
This voting feature appears on all error messages that are thrown by calls to the Error(String) and
Error(ErrorInfo) methods.

User gave feedback on error message


Occurs when a use selects either Yes or No to the question on the error dialog as to whether the message was
helpful.
General dimensions
The following table explains the general dimensions included in the trace. The table lists the dimensions that are
specific to Business Central.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message **User gave feedback on error Not OK]**


message: [OK

Custom dimensions
The following table explains the custom dimensions included in the trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId CL0002

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .
DIM EN SIO N DESC RIP T IO N O R VA L UE

alObjectId Specifies the ID of the AL object that threw the error.

alObjectName Specifies the ID of the AL object that threw the error.

alObjectType Specifies the ID of the AL object that threw the error.

alStackTrace Specifies the stack trace in AL code for the error.

appId Specifies the ID of the extension that threw the error.

appName Specifies the name of the extension that threw the error.

appVersion Specifies the version of the extension that threw the error.

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentName Specifies the name of the tenant environment. This


dimension isn't included with Business Central on-premises.
See Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

errorMessage Specifies the error shown to the user.

exceptionId Specifies the GUID assigned to the error.

userFeedback Specifies what the user voted, which can be either Yes or
No .

userLocale Specifies the regional language version of the message. The


value is a language culture name, like en-US for English US
and da-DK for Danish.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Error Method Telemetry
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 1 and later

When a user gets an error dialog while working in Business Central, a telemetry signal is emitted, which can be
logged in an Application Insights resource.
This telemetry data let's you identify and analyze calls to the ERROR method from AL code. You can also set up
alerts in Azure Monitor to get notified if many users experience errors.

Error dialog displayed


Occurs when the Error method is called and displays a dialog to the user.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Error dialog displayed: {failureReason}

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId RT0030

alErrorMessage The error string defined in error method and displayed in the
client.

If the error message wasn't a text constant, you get the


message
Use ERROR with a text constant to improve telemetry
details
instead of the actual message.

Some messages can contain customer data. As a precaution,


Business Central only emits information that's classified as
SystemMetadata. Information that belongs to other data
classifications, like customer data, isn't shown. Instead, the
following message is shown: "Message not shown because
the NavBaseException(string, Exception, bool) constructor
was used."

alObjectId Specifies the ID of the AL object.

alObjectType Specifies the type of the AL object.

alStackTrace Specifies the stack trace in AL.


DIM EN SIO N DESC RIP T IO N O R VA L UE

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName The display name of the Business Central company that was
used at time of execution

failureReason Dialog means the error was the result of an error method
call in AL. Errors thrown by the platform have other reasons,
like MetadataNotFound.

Common custom dimensions


The following table explains other custom dimensions that are common to all extension update traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId The Azure Active Directory (Azure AD) tenant ID that's used
for Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

component Dynamics 365 Business Central Ser ver

componentVersion The version number of the component that emits telemetry


(see the component dimension)

environmentName The name of the tenant environment. See Managing


Environments. This dimension isn't included for Business
Central on-premises environments.

environmentType The environment type for the tenant, such as Production ,


Sandbox, Trial. See Environment Types

telemetrySchemaVersion The version of the Business Central telemetry schema

See also
Upgrading Extensions
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Dialog.Error Method
Dialog.Error Method
Analyzing Extension Lifecycle Trace Telemetry
2/6/2023 • 42 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1, version 16.3. Extension-level support introduced in
2020 release wave 2, version 17.1.
Extension lifecycle telemetry gathers data about the success or failure of the following extension-related
operations:
Compiling an extension
Synchronizing an extension
Publishing an extension
Installing an extension
Updating an extension
Uninstalling an extension
Unpublishing an extension
Failed operations result in a trace log entry that includes a reason for the failure.
Traces are recorded for operations started initiated from any of the following components, depending whether
you have Business Central online or on-premises:

C O M P O N EN T O N L IN E O N - P REM ISES

Extension Management page in the


Business Central client.

Manage Apps page in the Business


Central admin center.

App Management API of the Business


Central admin center.

Extension management PowerShell


cmdlets from the Business Central
Administration Shell

Business Central control plane, which


is the online service managed by
Microsoft.

NOTE
For some operations, you might experience that certain custom dimensions aren't available. The reason is that custom
dimensions are added to the signal gradually, as the information is retrieved. If the operation fails before the custom
dimension is retrieved, it isn't included in the result. For example, if you try to uninstall an extension using the Ininstall-
NAVApp cmdlet, and the specified extension name is wrong, the operation fails. In this case, the extensionid and
extensionVersion will be excluded from the results.

ENVIRONMENT/SERVER TRACES
The traces in this section are recorded for extensions that are published to the environment/server in the tenant
scope only.
For on-premises, it includes extensions that are published by running the Publish-NAVApp cmdlet with
the -Scope Tenant parameter.
For online, it includes per-tenant extensions uploaded from the Extension Management page in the
client. It doesn't include Microsoft extensions or AppSource extensions.

Extension compiled successfully


Occurs when an extension compiles successfully on the service. An extension compiles when it's published or
when it's repaired by using the Repair-NAVApp cmdlet.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension compiled successfully: {extensionName}


version {extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0020

extensionCompilationDependencyList Specifies details about the extensions on which the compiled


extension has dependencies.

Note: If the value exceeds 8000 characters, one or two


additional dimensions will be included in the trace to cover
the complete dependency list. For more information, see
About Custom Dimensions.

extensionCompilationResult Compilation succeeded without errors or warnings.

extensionName Specifies the name of the extension that was compiled.

extensionId Specifies the ID of the extension that was compiled.

extensionPublishedAs Specifies whether the compiled extension was published as


one of the following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.


DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.

extensionVersion Specifies the version of the compiled extension.

result Success

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Common custom dimensions


The following table explains custom dimensions that are common to all traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

component Dynamics 365 Business Central Ser ver .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Extension failed to compile


Occurs when an extension failed to compile on the service. An extension compiles when it's published or when
it's repaired by using the Repair-NAVApp cmdlet.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension failed to compile: {extensionName} version


{extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0021

extensionCompilationDependencyList Specifies details about the extensions on which the compiled


extension has dependencies.

Note: If the value exceeds 8000 characters, one or two


additional dimensions will be included in the trace to cover
the complete dependency list. For more information, see
About Custom Dimensions.

extensionCompilationResult Specifies details about the error that occurred during


compilation.

extensionName Specifies the name of the extension that failed to compile.

extensionId Specifies the ID of the extension that failed to compile.

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.

extensionVersion Specifies the version of the compiled extension.

failureReason Specifies the error that occurred when compiling the


extension.

result Failure
DIM EN SIO N DESC RIP T IO N O R VA L UE

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Extension published successfully


Occurs when an extension published successfully on the service.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension published successfully: {extensionName}


version {extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0014

extensionId Specifies the ID of the extension that was published.

extensionIsRad Specifies whether the extension that was RAD published.


True indicates the extension was RAD published. False
indicates normal publishing.

RAD (Rapid Application Development) publishing is done


from the AL development environment. RAD publishing is a
partial publishing operation that only publishes objects
application objects that have changed during development.
For more information, see Work with Rapid Application
Development.

extensionName Specifies the name of the extension that published.

extensionId Specifies the ID of the extension that published.

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.


DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.

extensionVersion Specifies the version of the published extension.

result Success

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Extension failed to publish


Occurs when an extension failed publish on the service.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension failed to publish: {extensionName} version


{extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0015

extensionId Specifies the ID of the extension that was published.


DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionIsRad Specifies whether the extension that was RAD published.


True indicates the extension was RAD published. False
indicates normal publishing.

RAD (Rapid Application Development) publishing is done


from the AL development environment. RAD publishing only
is a partial publishing operation that only publishes objects
application objects that have changed during development.
For more information, see Work with Rapid Application
Development.

extensionName Specifies the name of the extension that published.

extensionId Specifies the ID of the extension that published.

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.

extensionVersion Specifies the version of the published extension.

failureReason Specifies the error that occurred when publishing.

result Failure

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Extension unpublished successfully


Occurs when an extension was unpublished successfully on the service.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension unpublished successfully: {extensionName}


version {extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0018

extensionId Specifies the ID of the extension that was unpublished.

extensionName Specifies the name of the extension that was unpublished.

extensionId Specifies the ID of the extension that was unpublished.

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.

extensionVersion Specifies the version of the unpublished extension.

result Success

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.
DIM EN SIO N DESC RIP T IO N O R VA L UE

See common custom dimensions

Extension failed to un-publish


Occurs when an extension fails to unpublish on the service.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension failed to un-publish: {extensionName}


version {extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0019

extensionId Specifies the ID of the extension that failed to unpublish.

extensionName Specifies the name of the extension that failed to unpublish.

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.

extensionVersion Specifies the version of the unpublished extension.

failureReason Specifies the error that occurred when unpublishing.

result Failure

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.
DIM EN SIO N DESC RIP T IO N O R VA L UE

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

TENANT TRACES
The traces in this section are recorded for synchronizing, installing and updating extensions on a tenant.
Synchronizing extensions
For on-premises, data for this operation is recorded when an extension is synchronized by using
the Sync-NAVApp cmdlet.
For online, data is recorded when an extension is installed from the Extension Management
page in the client. Or, when upgraded from the Manage Apps page in the Business Central
administration center.
Installing and uninstalling extensions
For on-premises, data for these operations is recorded when an extension is installed or
uninstalled by using the Install-NAVApp cmdlet or Uninstall-NAVApp cmdlet. Or, when an
extension is installed or uninstalled from the Extension Management page in the client.
For online, data for these operations is recorded when an extension is installed or uninstalled from
the Extension Management page in the client.
Updating an extension
For on-premises, data for this operation is recorded when an extension is upgraded by using the
Start-NAVAppDataUpgrade cmdlet.
For online, data is recorded when an extension is updated from the Manage Apps page in the
Business Central administration center.

Extension synchronized successfully


Occurs when an extension synchronizes successfully on the tenant.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension synchronized successfully:


{extensionName} version {extensionVersion} by
{extensionPublisher} ({extensionId})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0012

extensionId Specifies the ID of the extension that was synchronized.

extensionName Specifies the name of the extension that was synchronized.

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.

extensionSynchronizationMode Specifies whether the extension was synchronized in one of


the following modes:
Add - The database schema defined by the objects in
the extension are added to the database schema of
the tenant database. This mode is typically used
mode after you publish an extension for the first
time.
Clean - The database schema defined by all versions
of the extension will be removed from the database
and all data is lost. This mode is typically used when
an extension will no longer be used and all versions
unpublished.
Development - This mode is acts similar to Add,
except it's intended for use during development. It
lets you sync the same version of an extension that is
already published. However, to run this mode, only
one version the App can be currently published.
ForceSync - This mode like Add except it supports
destructive schema changes (like removing fields,
renaming them, changing their datatypes, and more).
it's typically used during development, and is the
mode used when an extension is published and
installed from the AL development environment.
For more information about the modes, see Sync-NAVApp
cmdlet -Mode.

extensionVersion Specifies the version of the extension was synchronized.

result Success

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.
DIM EN SIO N DESC RIP T IO N O R VA L UE

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Extension synchronized failed


Occurs when an extension fails to synchronize on the tenant.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension failed to synchronize: {extensionName}


version {extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0013

extensionId Specifies the ID of the extension that failed to synchronize.

extensionName Specifies the name of the extension that failed to


synchronize.

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.
DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionSynchronizationMode Specifies whether the extension was synchronized in one of


the following modes:
Add - The database schema defined by the objects in
the extension are added to the database schema of
the tenant database. This mode is typically used
mode after you publish an extension for the first
time.
Clean - The database schema defined by all versions
of the extension will be removed from the database
and all data is lost. This mode is typically used when
an extension will no longer be used and all versions
unpublished.
Development - This mode is acts similar to Add,
except it's intended for use during development. It
lets you sync the same version of an extension that is
already published. However, to run this mode, only
one version the App can be currently published.
ForceSync - This mode like Add except it supports
destructive schema changes (like removing fields,
renaming them, changing their datatypes, and more).
it's typically used during development, and is the
mode used when an extension is published and
installed from the AL development environment.
For more information about the modes, see Sync-NAVApp
cmdlet -Mode.

extensionVersion Specifies the version of the extension was synchronized.

failureReason Specifies the error that occurred when synchronizing the


extension.

result Failure

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Extension is already synchronized


Occurs when an extension was already synchronized on the tenant. Added in version 21.1.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension is already synchronized: {extensionName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0056

extensionId Specifies the ID of the extension that failed to synchronize.

extensionName Specifies the name of the extension that failed to


synchronize.

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.
DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionSynchronizationMode Specifies whether the extension was synchronized in one of


the following modes:
Add - The database schema defined by the objects in
the extension are added to the database schema of
the tenant database. This mode is typically used
mode after you publish an extension for the first
time.
Clean - The database schema defined by all versions
of the extension will be removed from the database
and all data is lost. This mode is typically used when
an extension will no longer be used and all versions
unpublished.
Development - This mode is acts similar to Add,
except it's intended for use during development. It
lets you sync the same version of an extension that is
already published. However, to run this mode, only
one version the App can be currently published.
ForceSync - This mode like Add except it supports
destructive schema changes (like removing fields,
renaming them, changing their datatypes, and more).
it's typically used during development, and is the
mode used when an extension is published and
installed from the AL development environment.
For more information about the modes, see Sync-NAVApp
cmdlet -Mode.

extensionVersion Specifies the version of the extension was synchronized.

failureReason Specifies the error that occurred when synchronizing the


extension.

result Failure

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Extension installed successfully


Occurs when an extension installs successfully on a tenant.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension installed successfully: {extensionName}


version {extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0010

extensionId Specifies the ID of the extension that was installed.

extensionName Specifies the name of the extension that was installed.

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.

extensionVersion Specifies the version of the extension that was installed.

result Success

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Dependent extension installed successfully


Occurs when an extension is installed because another extension that depends on it was installed. This event is
only available from version 18.1 and later.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Dependent Extension installed successfully:


{extensionName} version {extensionVersion} by
{extensionPublisher} ({extensionId})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0026

extensionId Specifies the ID of the extension that was installed.

extensionName Specifies the name of the extension that was installed.

extensionPublisher Specifies the extension's publisher.

extensionVersion Specifies the version of the extension that was installed.

parentExtensionId Specifies the ID of the other extension that required the


installation this extension.

See common custom dimensions

Extension failed to install


Occurs when an extension failed to install on a tenant.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension failed to install: {extensionName} version


{extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0011

extensionId Specifies the ID of the extension that failed to uninstall.

extensionName Specifies the name of the extension that failed to uninstall.


DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.

extensionVersion Specifies the version of the extension that was installed.

failureReason Specifies the error that occurred when the extension was
installed.

result Failed

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Extension un-installed successfully


Occurs when an extension is successfully uninstalled from a tenant.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension un-installed successfully: {extensionName}


version {extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0016

doNotSaveData Specifies whether the uninstall operation was run with


option not to save the data in database table fields that are
added by the extension. When using the Uninstall-NAVApp
cmdlet, this condition is set with the -DoNotSaveData switch
parameter.

extensionId Specifies the ID of the extension that was uninstalled.

extensionName Specifies the name of the extension that was uninstalled.

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.

extensionVersion Specifies the version of the extension was uninstalled.

result Success

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Dependent extension un-installed successfully


Occurs when an extension is uninstalled because an extension that it's dependent on was uninstalled. This event
is only available from version 18.1 and later.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Dependent extension un-installed successfully:


{extensionName} version {extensionVersion} by
{extensionPublisher} ({extensionId})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0027

doNotSaveData Specifies whether the uninstall operation on the parent


extension was run with option not to save the data in
database table fields that are added by the extension. When
using the Uninstall-NAVApp cmdlet, this condition is set with
the -DoNotSaveData switch parameter.

extensionId Specifies the ID of the dependent extension that was


uninstalled.

extensionName Specifies the name of the dependent extension that was


uninstalled.

extensionPublisher Specifies the dependent extension's publisher.

extensionVersion Specifies the version of the dependent extension was


uninstalled.

parentExtensionId Specifies the ID of the extension that the uninstalled


extension is dependent on.

See common custom dimensions

Extension failed to un-install


Occurs when an extension failed to uninstall on a tenant.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension failed to un-install: {extensionName}


version {extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0017
DIM EN SIO N DESC RIP T IO N O R VA L UE

doNotSaveData Specifies whether the uninstall operation was run with


option not to save the data in database table fields that are
added by the extension. When using the Uninstall-NAVApp
cmdlet, this condition is set with the -DoNotSaveData switch
parameter.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

extensionId Specifies the ID of the extension that failed to uninstall.

extensionName Specifies the name of the extension that failed to uninstall.

extensionPublishedAs Specifies whether the extension was published as one of the


following options:
Dev - published from the AL development
environment.
Global - published to the global scope.
Tenant - published to the tenant scope.

extensionPublisher Specifies the extension's publisher.

extensionScope Specifies whether the extension was published to one of the


following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the
tenant to which it was published.

extensionVersion Specifies the version of the extension that failed to uninstall.

failureReason Specifies the error that occurred when the extension was
uninstalled.

result Failure

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions


Extension updated successfully
Occurs when an extension updates successfully on the service.

NOTE
Data is also recorded for any upgrade code that was run. For more information, see Analyzing Extension Update Trace
Telemetry.

General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension updated successfully: {extensionName}


version {extensionVersion} by {extensionPublisher}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId LC0022

extensionCulture Specifies the language version for which the extension that
was upgraded. The value is a language culture name, such as
en-US or da-DK . If a language wasn't specified when the
extension was installed, then en-US is used by default.

extensionId Specifies the ID of the extension that failed to uninstall.

extensionName Specifies the name of the extension that was being


upgraded.

extensionPublisher Specifies the extension's publisher.

extensionVersion Specifies the new version of the extension being upgraded.

extensionVersionFrom Specifies the old version of the extension being upgraded.

result Success

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the request


executed.
DIM EN SIO N DESC RIP T IO N O R VA L UE

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Extension failed to update


Occurs when an extension failed to update on the service.

NOTE
Data is also recorded for any upgrade code that was run. For more information, see Analyzing Extension Update Trace
Telemetry.

General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension failed to update: {extensionName} version


{extensionVersion} by {extensionPublisher}
({extensionId})

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId LC0023

extensionCulture Specifies the language version for which the extension that
was upgraded. The value is a language culture name, such as
en-US or da-DK . If a language wasn't specified when the
extension was installed, then en-US is used by default.

extensionId Specifies the ID of the extension that failed to uninstall.

extensionName Specifies the name of the extension that was being


upgraded.

extensionPublisher Specifies the extension's publisher.

extensionVersion Specifies the new version of the extension being upgraded.


DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionVersionFrom Specifies the old version of the extension being upgraded.

failureReason Specifies the error that occurred during upgrade.

result Failure

serverExecutionTime Specifies the amount of time it took the server to complete


the request. The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the request


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

totalTime Specifies the amount of time it took to process the request.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

CONTROL PLANE TRACES


APPLIES TO: Business Central online

The traces in this section are emitted by the Business Central control plane service during the installation or
update operation of an extension/app. Theses traces compliment the tenant traces described above and help
you identify the origin or cause of the extension's installation or update. The traces are recorded when:
The extension is explicitly installed or updated
The extension is installed or updated because an extension that's dependant on it was installed or updated.
A hotfix is applied to the extension by Microsoft or ISV embed partner.
The following table illustrates the traces you can expect to see with the installation or update of an extension, in
the order that they'll occur. The trace messages have been simplified for illustration purposes.

EXT EN SIO N IN STA L L L IF EC Y C L E EXT EN SIO N UP DAT E L IF EC Y C L E T RA C E SO URC E

Environment app version install Environment app version update Control plane
scheduled scheduled

Environment app version install Environment app version update Control plane
started started

Environment app version Environment app version Control plane


install/update requires dependency install/update requires dependency
app app

Extension synchronized: version Extension synchronized: version Tenant

Extension installed: version Extension updated: version Tenant


EXT EN SIO N IN STA L L L IF EC Y C L E EXT EN SIO N UP DAT E L IF EC Y C L E T RA C E SO URC E

Environment app version installed Environment app version updated Control plane

Environment app version installation scheduled for environment


Occurs when scheduling the installation of a new extension/app has completed successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionName}, version


{extensionDestinationVersion} installation scheduled
for environment: {environmentName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependencyUpdate A boolean that specifies whether dependent extensions will


be updated

allowPreviewVersion A boolean that specifies whether preview versions are


allowed.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0161

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.
DIM EN SIO N DESC RIP T IO N O R VA L UE

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app version installation scheduling failed for


environment
Occurs when scheduling the installation of a new extension/app has failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionName}, version


{extensionDestinationVersion} installation
scheduling failed for environment:
{environmentName}

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependencyUpdate A boolean that specifies whether dependent extensions will


be updated

allowPreviewVersion A boolean that specifies whether preview versions are


allowed.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0162

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionId Specifies the ID of the extension/app.


DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app version installation started for environment


Occurs when installing a new extension/app has started.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionName}, version


{extensionDestinationVersion} installation star ted
for environment: {environmentName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependencyUpdate A boolean that specifies whether dependent extensions will


be updated

allowPreviewVersion A boolean that specifies whether preview versions are


allowed.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0163

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app version installation succeeded for environment


Occurs when installing a new extension/app has completed successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionName}, version


{extensionVersion} installation succeeded for
environment: {environmentName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependencyUpdate A boolean that specifies whether dependent extensions will


be updated

allowPreviewVersion A boolean that specifies whether preview versions are


allowed.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0164

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

totalTime Specifies the total time the operation ran for.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app version installation failed for environment


Occurs when installing a new extension/app has failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionName}, version


{extensionDestinationVersion} installation failed for
environment: {environmentName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependentsUninstall A boolean that specifies whether dependent extensions will


be uninstalled.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0165

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionSourceVersion Specifies the current version of the extension/app.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app version installation/update requires automatically


installing a new dependency app for environment
Occurs when the extension/app that's being installed or updated has a dependency on another extension/app
that must be installed first.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionName}, version


{extensionDestinationVersion} installation/update
requires automatically installing a new dependency
app {dependencyExtensionName}, version
{dependencyExtensionDestinationVersion} for
environment: {environmentName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependencyUpdate A boolean that specifies whether dependent extensions will


be updated

allowPreviewVersion A boolean that specifies whether preview versions are


allowed.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

dependencyExtensionDestinationVersion Specifies the version of the dependency extension.

dependencyExtensionId Specifies the ID of the dependency extension/app.

dependencyExtensionName Specifies the name of the dependency extension/app.

dependencyExtensionPublisher Specifies the publisher of the dependency extension/app.

dependencyExtensionScope Specifies whether the dependency extension/app is


published to one of the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0166

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S
DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app update to version scheduled for environment


Occurs when scheduling the update of an existing extension/app to another version has succeeded.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionName} update to version


{extensionDestinationVersion} scheduled for
environment: {environmentName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependencyUpdate A boolean that specifies whether dependent extensions will


be updated

allowPreviewVersion A boolean that specifies whether preview versions are


allowed.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0167

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionSourceVersion Specifies the current version of the extension/app.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app update to version scheduling failed for environment


Occurs when scheduling the update of an existing extension/app to another version has failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionId} update to version


{extensionDestinationVersion} scheduling failed for
environment: {environmentName}

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependencyUpdate A boolean that specifies whether dependent extensions will


be updated

allowPreviewVersion A boolean that specifies whether preview versions are


allowed.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.
DIM EN SIO N DESC RIP T IO N O R VA L UE

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0168

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionId Specifies the ID of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

extensionSourceVersion Specifies the current version of the extension/app.

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app update to version started for environment


Occurs when updating of an existing extension/app to another version has started.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionId} update to version


{extensionDestinationVersion} star ted for
environment: {environmentName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependencyUpdate A boolean that specifies whether dependent extensions will


be updated

allowPreviewVersion A boolean that specifies whether preview versions are


allowed.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0169

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionId Specifies the ID of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

extensionSourceVersion Specifies the current version of the extension/app.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app update to version succeeded for environment


Occurs when updating of an existing extension/app to another version has completed successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionId} update to version


{extensionDestinationVersion} succeeded for
environment: {environmentName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependencyUpdate A boolean that specifies whether dependent extensions will


be updated

allowPreviewVersion A boolean that specifies whether preview versions are


allowed.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0170

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionId Specifies the ID of the extension/app.

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

extensionSourceVersion Specifies the current version of the extension/app.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

totalTime Specifies the total time the operation ran for.


DIM EN SIO N DESC RIP T IO N O R VA L UE

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app update to version failed for environment


Occurs when updating an existing extension/app to another version has failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionId} update to version


{extensionDestinationVersion} failed for
environment: {environmentName}

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependencyUpdate A boolean that specifies whether dependent extensions will


be updated

allowPreviewVersion A boolean that specifies whether preview versions are


allowed.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0171

extensionDestinationVersion Specifies the version of the extension/app to be installed or


updated to.S

extensionId Specifies the ID of the extension/app.


DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionScope Specifies whether the extension/app was published to one of


the following scopes:
Global - the extension can be installed on all tenants
connected the service instance.
Tenant - the extension can only be installed on the tenant
to which it was published.

extensionSourceVersion Specifies the current version of the extension/app.

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

totalTime Specifies the total time the operation ran for.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app uninstall scheduled for environment


Occurs when scheduling the uninstallation of an extension/app has completed successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionName} uninstall


scheduled for environment: {environmentName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependencyUpdate A boolean that specifies whether dependent extensions will


be updated

allowPreviewVersion A boolean that specifies whether preview versions are


allowed.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .
DIM EN SIO N DESC RIP T IO N O R VA L UE

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0173

extensionId Specifies the ID of the extension/app.

extensionName Specifies the name of the extension/app.

extensionPublisher Specifies the publisher of the extension/app.

extensionSourceVersion Specifies the current version of the extension/app.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

Environment app uninstall scheduling failed for environment


Occurs when scheduling the uninstallation of an extension/app has failed.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Environment app {extensionId} uninstall scheduling


failed for environment: {environmentName}

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

allowDependentsUninstall A boolean that specifies whether dependent extensions will


be uninstalled.

applicationFamily Specifies the application family for the environment, such as


BusinessCentral. For environments in the ISV embed
program, other values might show up here.

countryCode Specifies the localization for the environment, such as US or


DK .
DIM EN SIO N DESC RIP T IO N O R VA L UE

deleteData A boolean that specifies whether data will be deleted.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the version of the tenant environment.

environmentVersion Specifies the version of the tenant environment.

eventId LC0174

extensionId Specifies the ID of the extension/app.

failureReason Specifies the reason for the failure. Use this for
troubleshooting.

runAfterDateUtc Specifies the date and time (in UTC) after which the hotfix
can be applied.

useEnvironmentUpdateWindow A boolean value (true or false) that specifies whether to use


the update window that's defined in the Business Central
admin center.

See common custom dimensions -

See also
Upgrading Extensions
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Extension Update Telemetry
2/6/2023 • 4 minutes to read • Edit Online

INTRODUCED IN: Exception telemetry was introduced in Business Central 2020 release wave 1, version 16.2.
Upgrade tag telemetry was introduced in Business Central 2021 release wave 1, version 18.1.
Extension upgrade telemetry gathers information about operations that can occur during extension upgrades:
Upgrade code failures
The telemetry provides information about exceptions that are thrown by code run by upgrade codeunits.
The trace events include the following information:
The codeunit that threw the exception.
AL stack trace.
Exception message.
Upgrade tag usage
The telemetry provides information about calls to the AL methods HasUpgradeTag and SetUpgradeTag
from upgrade codeunits. These methods are provided by codeunit 9999 Upgrade Tag in the System
Application extension. Upgrade tags are used to control when upgrade code is run. For more information,
see Using upgrade tags to control upgrade code. This data can help you identify, troubleshoot, and
resolve issues in upgrade code.
The telemetry helps you troubleshoot and resolve code issues that block the data upgrade of per-tenant and
AppSource extensions.

Extension Update Failed: exception raised in extension


Occurs when an extension upgrade fails because of an exception in an upgrade codeunit.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Extension Update Failed: exception raised in


extension {extensionName} by {extensionPublisher}
(updating to version {extensionTargetedVersion})

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId RT0010

alObjectId The ID of the AL object that was run by request

alStackTrace The stack trace in AL


DIM EN SIO N DESC RIP T IO N O R VA L UE

companyName The display name of the Business Central company that was
used at time of execution

extensionName The name of the extension that was being upgraded

extensionId The AppID of the extension that was being upgraded

extensionTargetedVersion The new version of the extension being upgraded

extensionVersion The old version of the extension being upgraded

failureReason The exception that was thrown by the upgrade code. Some
exception messages can contain customer data. As a
precaution, Business Central only emits information that's
classified as SystemMetadata. Exception messages that
contain other data classifications, like customer data, aren't
shown. Instead, the following message is shown: "Message
not shown because the NavBaseException(string, Exception,
bool) constructor was used."

failureType DataUpdate

Common custom dimensions


The following table explains other custom dimensions that are common to all extension update traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId The Azure Active Directory (Azure AD) tenant ID that's used
for Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

component Dynamics 365 Business Central Ser ver

componentVersion The version number of the component that emits telemetry


(see the component dimension)

environmentName The name of the tenant environment. See Managing


Environments. This dimension isn't included for Business
Central on-premises environments.

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

environmentType The environment type for the tenant, such as Production ,


Sandbox, Trial. See Environment Types

telemetrySchemaVersion The version of the Business Central telemetry schema

Upgrade tag searched for


Occurs when the HasUpgradeTag method in codeunit 9999 Upgrade Tag is called from an upgrade codeunit
during an extension upgrade.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Upgrade tag searched for : {alUpgradeTag}

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000EJ9

alCategory ALUpgrade

alCompanyName The display name of the Business Central company that was
used at time of execution

alDataClassification OrganizationIdentifiableInformation

alObjectId 9996

alObjectName Upgrade Tag Impl.

alUpgradeTag The upgrade tag that was input to the HasUpgradeTag


method

alExecutionContext The context that the upgrade code was running in. The
dimension has the following values:
Install indicates the code was run during the
installation of the extension.
Upgrade indicates the code was run during the
upgrade of the extension.
Normal indicates the code was run by an operation
other than extension installation or upgrade. For
example, when a new company was added.

alValue true if the upgrade tag was found; otherwise, false .

extensionName System Application

extensionId The ID of the System Application extension

extensionPublisher The publisher of the System Application extension

extensionVersion The version of the System Application extension

See common custom dimensions

Upgrade tag set


Occurs when the SetUpgradeTag method in Codeunit 9999 Upgrade Tag is called from an upgrade codeunit
during an extension upgrade.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Upgrade tag searched for : {alUpgradeTag}

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000EJA

alCategory ALUpgrade

alCompanyName The display name of the Business Central company that was
used at time of execution

alDataClassification OrganizationIdentifiableInformation

alObjectId 9996

alObjectName Upgrade Tag Impl.

alUpgradeTag The upgrade tag that was set by the SetUpgradeTag


method.

alExecutionContext The context that the upgrade code was running in. The
dimension has the following values:
Install indicates the code was run during the
installation of the extension.
Upgrade indicates the code was run during the
upgrade of the extension.
Normal indicates the code was run by an operation
other than extension installation or upgrade. For
example, when a new company was added.

extensionName System Application

extensionId The ID of the System Application extension

extensionPublisher The publisher of the System Application extension

extensionVersion The version of the System Application extension

See common custom dimensions

See also
Upgrading Extensions
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Feature Telemetry
2/6/2023 • 3 minutes to read • Edit Online

The Telemetry AL module simplifies the way you monitor the health of your solution and the uptake of
application features. There are multiple benefits of using the module compared to sending telemetry via
Session.LogMessage . For example:

Different features can be compared across the same metrics.


Common information is sent together with every feature telemetry message, which allows for advanced
filtering capabilities.

Example: Register the use of a feature


It's easy to use the Feature Telemetry codeunit. For example, to register the usage of a feature, you can just use
the FeatureTelemetry.LogUsage(<tag>, <feature name>, <event name>); method. After the telemetry is emitted,
you can aggregate and display the data. For example, you can use the Feature Usage Power BI report. The
report is available on our BCTech GitHub repository.
There are three kinds of events that a feature can log through the Feature Telemetry codeunit.
FeatureTelemetry.<LogUsage|LogError|LogUptake>(...)

LogUsage should be called when the feature is successfully used by a user.


LogError should be called when an error must be explicitly sent to telemetry. For example, after a call to a
try function, when Codeunit.Run returned false, when sending an http response error message, and so on.
LogUptake should be called when a user changes the uptake state of a feature. There are four uptake states
for features:
Undiscovered
Discovered
Set up
Used

NOTE
Tracking the uptake status of a feature may make database transactions. If LogUptake is called from within a try
function, the PerformWriteTransactionsInASeparateSession parameter should be set to True .

Calling LogUptake when the uptake state is Undiscovered resets the uptake state of the feature. The telemetry
from this call will be used to calculate the values in the uptake funnel of the feature.

Log uptake
If a feature logs uptake, there should be calls to register the Discovered , Set up , and Used states. The
following list describes the current convention for registering uptake states:
Discovered should be registered when pages related to the given feature are opened (or when a user looks
for information about a feature).
Set up should be registered when the user performed a set up for the feature (usually right after a record in
a table related to the feature is added or updated).
Used should be registered when a user attempts to use the feature (note the difference with LogUsage,
which should be called only if the feature is used successfully).
If LogUptake is called from a try function, the PerformWriteTransactionsInASeparateSession parameter should be
set to true .

Feature and event names


Feature names should be short and easy to identify. For example, Retention policies, Configuration packages,
and Emailing. Event names should specify the scenario being executed. If LogUsage is called, the event name
should use the past tense because the event has already happened. For example, Email sent or
Retention policy applied . If LogError is called, the event name should use the present tense. For example,
Sending email , Loading template ).

General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Depends on the event.


DIM EN SIO N DESC RIP T IO N O R VA L UE

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alCategory FeatureTelemetr y .

alFeatureName The name of the feature being tracked.

alSubCategory Holds one of the values Uptake , Usage , or Error .

alFeatureUptakeStatus If alSubCategory holds the value Uptake , then the update


status can hold one the the following values: Discovered ,
Set up , Undiscovered , or Used .

alCallerAppName The name of the extension that emitted telemetry.

alCallerAppVersionMajor The major version of the extension that emitted telemetry.

alCallerAppVersionMinor The minor version of the extension that emitted telemetry.

alClientType The client type of the session.

alCompany The current company name.

alIsEvaluationCompany Whether the current company is an evaluation company.

alTenantLicenseState The license state of the tenant.

alIsAdmin Whether the current user is a tenant admin or delegated


admin.

alCountryCode Specifies the localization for the environment, such as US or


DK .

alDataClassification SystemMetadata . Fixed and set by the Feature Telemetry


codeunit.

alObjectId 8713 . The object ID of the Feature Telemetry codeunit.

alObjectName System Telemetr y Logger . The name of the codeunit


used by the Feature Telemetry codeunit.

alUserRole The profile ID associated with the user in the User


Personalization table.
DIM EN SIO N DESC RIP T IO N O R VA L UE

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension).

environmentName Specifies the name of the tenant environment. See


Managing Environments. This dimension isn't included for
Business Central on-premises environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

eventId Unique event ID for different feature telemetry events.

See Also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Feature Telemetry sample
Analyzing Field Monitoring Telemetry
2/6/2023 • 3 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 (update 17.1) and later

Keeping sensitive data secure and private is a core concern for most businesses. To add a layer of security, you
can monitor important fields when someone changes a value. For example, you might want to know if someone
changes your company's IBAN number.
To gather this data, you'll have to start field monitoring and specify the fields that you want to monitor. For more
information, see Auditing Changes in Business Central - Monitoring Sensitive Fields in the Application help.
Telemetry is then logged for the following operations:
When field monitoring is stopped or started
When a field is added or removed for monitoring (only in version 18.0 and later)
When a field value is changed

Sensitive field monitor status changed


Occurs when the field monitor feature is started or stopped in the company.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Sensitive field monitor status has changed to


{almonitorStatus}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000DD3

alMonitorStatus Yes - the field monitor feature was started.

No the field monitor feature was stopped. This dimension is


called "almonitorStatus" before version 18.0.

alObjectId 1392

alObjectName Monitor Sensitive Field

alObjectType CodeUnit

Common custom dimensions


The following table explains other custom dimensions that are common to all field monitoring traces.
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alDataClassification SystemMetadata

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

environmentName Specifies the name of the tenant environment. See


Managing Environments. This dimension isn't included for
Business Central on-premises environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

extensionName Specifies the name of the base application.

extensionId Specifies the ID of the base extension.

extensionPublisher Specifies the publisher of the extension.

extensionVersion Specifies the version of the base application.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Sensitive field value has changed


Occurs the value of a monitored field has changed in the company.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

alTableNumber Specifies the ID of the table where the changed field is


included. This dimension was introduced in version 18.0.

message Sensitive field value has changed: {alfieldCaption}


({alFieldNumber}) in table {altableCaption}
({alTableNumber})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000CTE

alFieldCaption Specifies the name of the field that was changed. This
dimension is called "alfieldCaption" before version 18.0.

alFieldNumber Specifies the ID of the field that was changed. This dimension
was introduced in version 18.0.

alTableCaption Specifies the name of the table that includes the changed
field. This dimension is called "altableCaption" before version
18.0.

alTableNumber Specifies the ID of the table that includes the changed field.
This dimension was introduced in version 18.0.

alObjectId 1367

alObjectName Monitor Sensitive Field Data

alObjectType CodeUnit

See common custom dimensions

NOTE
Changes to fields in the following tables are always logged:
Fields in the Field Monitoring Setup table. Many of the fields are included on the Field Monitoring Setup page.
Fields in the Change Log Setup (Field) table. Many of the fields are included on the Field Monitoring
Worksheet page.
The Contact Email field in the User table.

Sensitive field added to or removed from monitor


Occurs when a field has been added to or removed from monitoring. This dimension was introduced in version
18.0.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Sensitive field added to monitor : {alfieldCaption}


({alFieldNumber}) in table {alTableCaption}
({alTableNumber})
or
Sensitive field removed from monitor :
{alfieldCaption} ({alFieldNumber}) in table
{alTableCaption} ({alTableNumber})

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000EMW

alFieldCaption Specifies the name of the field that was added or removed.

alFieldNumber Specifies the ID of the field that was added or removed.

alTableNumber Specifies the ID of the table that includes the added or


removed field.

alTableCaption Specifies the name of the table that includes the added or
removed field.

alObjectId 1367

alObjectName Monitor Sensitive Field Data

alObjectType CodeUnit

See common custom dimensions

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Job Queue Lifecycle Trace Telemetry
2/6/2023 • 5 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2, version 17.2, and later
Job queue lifecycle telemetry gathers data about the following operations:
A job queue entry was enqueued.
A job queue entry was started.
A job queue entry finished. Provides information as to whether it was successful or failed.
For information about creating and managing job queue entries, see Use Job Queues to Schedule Tasks in the
Business Central application help.

Job queue entry enqueued


Occurs when a job queue entry is sent to the job queue to eventually be run. A job queue entry is sent to the
queue when its status is changed from On Hold to Ready or if it's a recurring job queue entry. Recurring job
queue entries are automatically enqueued after each run.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Job queue entr y enqueued: {alJobQueueId}

severityLevel 1

Custom dimensions
The following table explains custom dimensions that are specific to this trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E24

alJobQueueId Specifies the ID of the job queue entry.

alJobQueueIsRecurring Specifies whether the job queue is recurring. Yes indicates it's
recurring. No indicates it's not recurring.

alJobQueueObjectId Specifies the ID of the object that the job queue entry runs.

alJobQueueObjectType Specifies the type of the object that the job queue entry
runs, for example Repor t or Codeunit .

alJobQueueStatus Ready indicates it's a non-recurring job queue entry or the


first run of a recurring job queue entry that's ready to run.
On Hold with Inactivity Timeout indicates it's a
recurring job query entry that's ready to run.

Error
Information if the job queue entry fails to be sent to the queue.
General dimensions

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Job queue entr y not enqueued: {alJobQueueId}

severityLevel 2

Custom dimensions
The following table explains custom dimensions that are specific to this trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000FNY

See common custom dimensions

Success
Information if the job queue entry was successfully sent to the queue.
General dimensions

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Job queue entr y enqueued: {alJobQueueId}

severityLevel 1

Custom dimensions
The following table explains custom dimensions that are specific to this trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E24

See common custom dimensions

Job queue entry started


Occurs when a job queue entry starts to run.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Job queue entr y star ted: {alJobQueueId}

severityLevel 1

Custom dimensions
The following table explains custom dimensions that are specific to this trace.
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E25

See common custom dimensions

Job queue entry finished (request)


Occurs when a request for a job queue entry finishes running.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Job queue entr y finished: {alJobQueueId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E26

alJobQueueExecutionTimeInMs Specifies how many milliseconds it took to run the job queue
entry.

See common custom dimensions

Job queue entry finished (run)


Occurs when a job queue entry finishes running.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message JobID = {alJobQueueId}, ObjectType =


{alJobQueueObjectType}, ObjectID =
{alJobQueueObjectId}, Status = Finished, Result =
Success, Company = {alJobQueueCompanyName},
Scheduled Task Id = {alJobQueueScheduledTaskId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E26

See common custom dimensions

Job queue entry failed with error


Occurs when a job queue entry fails to run.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Job queue entr y errored: {alJobQueueId}

severityLevel 2

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000HE7

See common custom dimensions

Common custom dimensions


The following table explains custom dimensions that are common to all job queue entry traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

alCategory AL JobQueueEntries

alJobQueueCompanyName Specifies the current company.

alJobQueueScheduledTaskId Specifies the ID of the scheduled task.

alJobQueueEarliestStartDateTime Specifies the earliest start date/time for the job queue entry.

alJobQueueId Specifies the ID of the job queue entry.

alJobQueueIsRecurring Specifies if the job queue is recurring. True indicates it's


recurring. False indicates it's not recurring.

alJobQueueObjectId Specifies the ID of the object that the job queue entry runs.

alJobQueueObjectType Specifies the type of the object that the job queue entry
runs, for example Repor t or Codeunit .

alJobQueueStackTrace Specifies the AL stack trace of the job queue entry. This
dimension was introduced in version 20.5.

alJobQueueStatus Ready indicates it's a non-recurring job queue entry or the


first run of a recurring job queue entry that's ready to run.
In Process indicates it's being run. Error indicates it
encountered an error while running. On Hold indicates it's
being queued. Finished indicates it's finished without error.
On Hold with Inactivity Timeout indicates it's a
recurring job query entry that's ready to run.

alObjectId 1351 , which is the ID of the system application codeunit


that subscribes to the telemetry events.
DIM EN SIO N DESC RIP T IO N O R VA L UE

alObjectName Telemetr y Subscribers , which is the name of the system


application codeunit that subscribes to the telemetry events.

alObjectType CodeUnit

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

extensionName Specifies the name of the extension that contains the object
run by the job queue entry.

extensionId Specifies the ID of the extension that contains the object run
by the job queue entry.

extensionVersion Specifies the version of the extension that contains the


object run by the job queue entry.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Event IDs
The following table describes the event IDs that are currently emitted.

JO B Q UEUE STAT US EVEN T ID DESC RIP T IO N

Enqueued AL0000FNY Occurs when a job queue entry fails to


enqueue and this happens if no task
scheduler is created behind it.

Enqueued AL0000E24 Occurs when a job queue entry


successfully enqueues and will after the
specified
alJobQueueEarliestStartDateTime.

Started AL0000E25 Occurs right before the


Job Queue Start codeunit is
triggered and that codeunit will run
the specified Object ID to run .
JO B Q UEUE STAT US EVEN T ID DESC RIP T IO N

Finished successfully AL0000E26 Occurs at the very end of the job


queue run.

Error AL0000HE7 Occurs when a job queue errors, and


this is the first thing that is triggered
before the updating of records.

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Use Job Queues to Schedule Tasks
Analyzing Long Running AL Methods Telemetry
2/6/2023 • 3 minutes to read • Edit Online

> APPLIES TO: Business Central 2020 release wave 2 and later, version 17.1. Available in extension telemetry
starting with version 18.1.
The Business Central Server server will emit telemetry about the execution time of long running AL methods,
including the time spent in the database. The signal also includes a breakdown of how much time each event
subscriber added to the total time. As a partner, this data gives you insight into bad performing code and
enables you to troubleshoot performance issues caused by extensions.

NOTE
To collect this telemetry for Business Central on-premises, the AL Function Timing and AL Function Logging
Threshold - Application Insights settings must be configured on the Business Central Server instance. For more
information, see Configuring Business Central Server. With Business Central online, this telemetry is enabled with a
specific threshold on a case-by-case basis by the service.

General dimensions
The following table explains the general dimensions included in the trace. The table lists the dimensions that are
specific to Business Central.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Operation exceeded time threshold (AL method)

severityLevel 2

CustomDimensions
This table describes the different dimensions of a Operation exceeded time threshold (AL method)
operation.

C O L UM N ( K EY ) DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


when using Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alMethod The name of the long running AL method.

alObjectId The type of the AL object that executed the AL method.

alObjectName The name of the AL object that executed the AL method.

alObjectType The type of the AL object that executed the AL method.

alStackTrace The stack trace in AL.


C O L UM N ( K EY ) DESC RIP T IO N O R VA L UE

clientType Specifies the type of client that executed the AL method,


such as Background or Web. For a list of the client types, see
ClientType Option Type.

companyName The display name of the Business Central company that was
used at time of execution.

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

environmentType Specifies the environment type of the Business Central


solution, such as Production or Sandbox.

environmentName Specifies the environment name of the Business Central


solution, such as Production or Sandbox.

eventId RT0018

executionTime Specifies the total time that it took to execute the AL


method. The value has the format hh:mm:ss.sssssss.

extensionInfo Specifies information about individual extensions that


contributed to the execution time spent in the call stack up
until the point at which the long-running threshold was
exceeded and the trace was emitted. The following
information is included for each extension:
id - the ID of the extension.
extensionName - the name of the extension.
extensionVersion - the version of the extension.
extensionPublisher - the publisher of the
extension.
subscriberExecutionCount - the number of event
subscribers executed in this extension.
executionTime - the total execution time for this
extension in the call stack. The value has the format
hh:mm:ss.sssssss.

extensionName Specifies the name of the extension that was currently


executing when the long-running threshold was exceeded
and the trace was emitted.

extensionPublisher Specifies the publisher of the extension that was currently


executing when the long-running threshold was exceeded
and the trace was emitted.
C O L UM N ( K EY ) DESC RIP T IO N O R VA L UE

extensionVersion Specifies the version of the extension that was currently


executing when the long-running threshold was exceeded
and the trace was emitted.

extensionId Specifies the ID of the extension that was currently executing


when the long-running threshold was exceeded and the
trace was emitted.

longRunningThreshold Specifies the time that defines a long-running AL method,


after which the trace is emitted. The value has the format
hh:mm:ss.sssssss.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Monitoring and Analyzing Long Running SQL Queries On-Premises
The Business Central Administration Center
Analyzing Long Running Operation (SQL Query)
Telemetry
2/6/2023 • 5 minutes to read • Edit Online

Any SQL query that takes longer than 750 milliseconds to execute will be sent to your Azure Application Insights
resource. This enables you to focus on tuning SQL queries that take too long to execute (maybe one or more
tables miss an index or maybe some filters are missing). It also reduces the ingestion of data into the Azure
Application Insights resource to save cost of having telemetry.
If you want to capture all SQL queries for a short period of time for a given session, you can enable Additional
logging from the Help & Suppor t page. This lets you analyze queries that take a short time to run but happen
very frequently. For Business Central online, additional logging is available on production environments running
version 17.4 or later. For Business Central on-premises, additional logging is available on environments running
version 18.6 or later.

NOTE
With Business Central on-premises, you can change the threshold that defines long running queries. For more
information, see Defining Long Running SQL Queries Threshold.

There are multiple reasons that affect the time it takes SQL queries to run. For example, the database could be
waiting for a lock to be released. Or, the database is executing an operation that does badly because of missing
indexes. Sometimes you can look at the SQL statement that was generated by the code to see what caused the
delay. This information is found in the CustomDimension data, specifically the AL Stack Trace column.

Dimensions in Application Insights


This table explains the columns included in long running query events emitted to Application Insights. Bold text
indicates that the value of the columns is a constant. Some columns are standard for Application Insights. These
columns are indicated by Application Insights.

C O L UM N DESC RIP T IO N O R VA L UE

timestamp Specifies the date and time that the long running query
event occurred, such as 2019-08-20T07:23:07.9996696Z

message Version 16.1 and later:


Operation exceeded time threshold (SQL quer y)

Before version 16.1:


Action took longer than expected

severityLevel 2 (This level indicates a warning. Long running queries are


always recorded as warnings)

itemType trace

customDimensions (see table that follows)

operation_Name Long Running Operation (SQL Quer y)

Note: The use of the operation_Name column was


deprecated in version 16.1. In future versions, data won't be
stored in this column. So in version 16.1 and later, use the
custom dimension column eventID column custom in
Kusto queries instead of operation_Name .

operation_Id Specifies the GUID assigned to the client operation. An


operation is created whenever the user does something in
the client, such as selecting an action.

operation_ParentId Currently this column is the same as the operation_Id. This


behavior might change in a future release.

session_Id Specifies the GUID of the client session. When a client makes
a connection to the Business Central Server instance, a
session is created and assigned an ID.

client_Type Application Insights

client_IP Application Insights

client_City Application Insights

client_StateOrProvince Application Insights

client_CountryOrRegion Application Insights


C O L UM N DESC RIP T IO N O R VA L UE

cloud_RoleName Specifies the display name of Business Central tenant. For


on-premises, this value is the same as the
cloud_RoleInstance.

cloud_RoleInstance Specifies the name of Business Central tenant.

appId Application Insights

appName Application Insights

iKey Application Insights

sdkVersion Application Insights

CustomDimensions
This table describes the different dimensions of a Long Running Operation (SQL Quer y) operation.

C O L UM N ( K EY ) DESC RIP T IO N O R VA L UE

extensionVersion Specifies the version of the extension.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentType Specifies the environment type of the Business Central


solution, such as Production or Sandbox.

environmentName Specifies the environment name of the Business Central


solution, such as Production or Sandbox.

extensionName Specifies the name of the extension.

alObjectType The type of the AL object that executed the SQL statement

alObjectName The name of the AL object that executed the SQL statement

alStackTrace The stack trace in AL.

companyName The display name of the Business Central company that was
used at time of execution.

extensionId Specifies the AppID of the extension.

eventId RT0005

This dimension was introduced in Business Central 2020


release wave 1, version 16.1.

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


when using Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web. For a list of the client types, see
ClientType Option Type.

alObjectId The type of the AL object that executed the SQL statement.

component Specifies the Business Central Server instance name and the
platform version.

executionTime Specifies the time that it took to execute the SQL


statement**. The value has the format hh:mm:ss.sssssss.

longRunningThreshold Specifies the amount of time that an SQL query can run
before a warning event is recorded. The value has the format
hh:mm:ss.sssssss.

This threshold is controlled by the Business Central Server


configuration setting called SqlLongRunningThreshold.

sqlStatement Specifies the SQL statement that was executed for the long
running query. The value is limited to 8192 characters. If the
value exceeds 8192 characters, it will be truncated in manner
that still provides the most pertinent information.
C O L UM N ( K EY ) DESC RIP T IO N O R VA L UE

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

** From telemetrySchemaVersion 0.6 and onwards, this value also includes the CompanyOpen operation.

Example
The following code snippet shows an example of the CustomDimensions.
{"extensionVersion":"16.0.10962.0","telemetrySchemaVersion":"0.3","componentVersion":"15.0.40494.0","environmentType":"Production","environmentName":"Production","
Application","alObjectType":"Report","alObjectName":"Suggest Worksheet Lines","alStackTrace":"AppObjectType: Report\r\n AppObjectId: 840\r\n AL CallStack: \"Sugges
(Report 840).DeleteEntries line 10 - Base Application by Microsoft\r\n\"Suggest Worksheet Lines\"(Report 840).\"Cash Flow Forecast - OnPostDataItem\"(Trigger) line
Application by Microsoft\r\n\"Cash Flow Management\"(CodeUnit 841).UpdateCashFlowForecast line 32 - Base Application by Microsoft\r\n\"Cash Flow Forecast Update\"(
842).OnRun(Trigger) line 18 - Base Application by Microsoft\r\n\"Job Queue Start Codeunit\"(CodeUnit 449).OnRun(Trigger) line 11 - Base Application by Microsoft\r\
Dispatcher\"(CodeUnit 448).HandleRequest line 30 - Base Application by Microsoft\r\n\"Job Queue Dispatcher\"(CodeUnit 448).OnRun(Trigger) line 19 - Base Applicatio
Microsoft","companyName":"CRONUS USA, Inc.","extensionId":"437dbf0e-84ff-417a-965d-ed2bb9650972","aadTenantId":"8ca62103-8877-486d-88e2-
9a91303abfc6","clientType":"Background","alObjectId":"840","component":"Dynamics 365 Business Central Server","executionTime":"00:00:05.7470000","sqlStatement":"DE
\"SQLDATABASE\".dbo.\"CURRENTCOMPANY$Cash Flow Forecast Entry$437dbf0e-84ff-417a-965d-ed2bb9650972\" WHERE (\"Cash Flow Forecast No_\"=@0)"}

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Monitoring and Analyzing Long Running SQL Queries On-Premises
The Business Central Administration Center
Analyzing Page View Telemetry
2/6/2023 • 5 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1, version 16.3. Available in extension telemetry from
version 18.0. Available in on-premises environments from version 21.0.
Page view telemetry gathers data about the pages that users open in the Business Central client. Each page view
tells you how long it took to open the page, information about the user's environment, and more.
Use the data to gather statistics about system usage and also troubleshoot performance issues caused by the
users' environments.

NOTE
In Application Insights, telemetry about page views is logged to the pageViews table and not the traces table like other
Business Central traces. This also means that you can use the built-in pages in the Usage feature of the Application
Insights to investigate how users interact with the Business Central environment. For more information, see Usage
analysis with Application Insights.

Page opened: {alObjectName}


Occurs when a page has been opened in the client.
General dimensions
The pageViews table is a built-in table in Application Insights. Here are some of the fields most used in analysis
of the signal:

F IEL D DESC RIP T IO N O R VA L UE

client_Browser Browser running on the client device.

client_OS Operating system of the client device.

client_Type Type of the client device.

duration Number of milliseconds it took the application to handle the


page view.

url URL of the page view.

name Name of the page opened in the client

session_id An identifier for the session. Can be used to create a timeline


of page views happening in the session

All fields are documented here: Application Insights PageViews Schema


Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alObjectId Specifies the ID of the page object that was opened.

alObjectName Specifies the name of the page object that was opened.

alObjectType Page

appId Specifies the ID of the extension that the page belongs to.

appName Specifies the name of the extension that the page belongs
to.

appPublisher Specifies the publisher of the extension that the page


belongs to.

appVersion Specifies the version of the extension that the page belongs
to.

clientType Specifies the type of client that opened the page such as
Background or Web . For a list of the client types, see
ClientType Option Type.

companyName The display name of the Business Central company that was
used when the page opened.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.
DIM EN SIO N DESC RIP T IO N O R VA L UE

designerLevel Specifies the design level in which the page was opened. This
dimension provides additional insight when the hostType
dimension is Designer .
None
The page wasn't opened in a design mode. This value
is shown when the hostType dimension is a value
other than Designer
Personalization
The page opened in the personalizing mode for
tailoring the page in the user's workspace only. See
Personalize Your Workspace.
Configuration
The page opened in customizing mode for tailoring
the page for all users of a specific profile. See
Customizing Pages for Profiles.
Development
The page opened in design mode for developing and
modifying the page from the client for all users. See
Using Designer.
Inspector
The page opened in page inspection mode for
viewing page information like source table, source
extension, and filters. See Inspecting Pages.
All - the page was opened in the personalization,
configuration, development, and inspector modes.

deviceLocale Specifies the preferred language that's configured for the


device that opened the page. For example, this dimension
could show the language setting of a browser used to view
the page. The value is a language code, such as en-US or
da-DK .

deviceScreenResolution Specifies the display resolution of the device that opened the
page. The value is given as {width}×{height}, with the units in
pixels. For example, 1024×768 means the width is 1024
pixels and the height is 768 pixels.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventID CL0001 (note that this is different from other signals where
the dimension is called eventId)

expandedFastTabs Specifies the FastTabs on the page that were expanded when
the page opened.

factboxExpanded Specifies whether the FactBox area was shown or hidden


when the page was opened. true indicates that the FactBox
was shown. false indicates that the FactBox was hidden.
DIM EN SIO N DESC RIP T IO N O R VA L UE

hostType Specifies the host that loads the page.


Device App
The page was loaded by a Business Central mobile
app, from a desktop, tablet, or phone.
Office add-in
The page was loaded by Office application, like Excel
or Outlook.
Designer
The page was loaded by the in-client designer, used
for changing page layout. The designer has different
modes. Each mode provides a different level of page
customization, as specified in the designerLevel
dimension.
Shim Browser
The page was loaded by the UWP (Universal
Windows Platform) application.
Browser
The page was loaded by web browser, like Microsoft
Edge or Google Chrome.

message Page opened: {alObjectName}

pageIsModal Specifies whether the page was opened as a modal page.


true indicates that the page was opened as a modal page;
otherwise, false .

pageMode Specifies whether the page was opened in one of the


following modes:
View indicates the page was opened for viewing only
Edit indicates the page was opened for making
changes
Create indicates the page was opened for creating a
new entity.
Select indicates the page was opened for selecting
an existing entity.
Delete indicates the page was opened for deleting
an entity.
The mode in which a page opened determined by different
things, like the RunPageMode Property or the URL used to
open the page.

pageType Specifies the type of page, such as Card , List , Document ,


and more. For a complete list of page types and descriptions,
see Page Types and Layouts.

refUri Specifies the URI of the page.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Permission Changes Trace Telemetry
2/6/2023 • 4 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2, version 17.2, and later
Permission changes telemetry gathers data about the following operations on permission sets:
A user-defined permission set was added or removed
A link between a user-defined permission set and system permission set was added or removed
A permission set was assigned to or removed from a user or user group
For information about managing permission sets, see Assign Permissions to Users and Groups.

User-defined permission set added


Occurs when a user-defined permission set is created.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message User-defined permission set added:


{alPermissionSetId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E2A

alNumberOfUserDefinedPermissionSets Specifies the total number of user-defined permission sets.

alPermissionSetId Specifies the ID assigned to the permission set.

Common custom dimensions


The following table explains additional custom dimensions that are common to all permission traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alCategory AL PermissionSet

alDataClassification SystemMetadata

alObjectId 1351 , which is the ID of the system application codeunit


that subscribes to the telemetry events.
DIM EN SIO N DESC RIP T IO N O R VA L UE

alObjectName Telemetr y Subscribers , which is the name of the system


application codeunit that subscribes to the telemetry events.

alObjectType CodeUnit

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

User-defined permission set removed


Occurs when a user-defined permission set is deleted.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message User-defined permission set removed:


{alPermissionSetId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E2B

alNumberOfUserDefinedPermissionSets Specifies the total number of user-defined permission sets.

alPermissionSetId Specifies the ID of the permission set that was deleted.

See common custom dimensions

Permission set link added


Occurs when a user-defined permission set is created from a copy of a system permission set, and the Notify
on Changed Permission Set option is selected. The Notify on Changed Permission Set option creates a
link between the system permission set and the user-defined permission set.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Permission set link added: {alSourcePermissionSetId}


-> {alLinkedPermissionSetId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E28

alSourcePermissionSetId Specifies the ID of the system permission set that was copied
to create the user-defined permission set.

alLinkedPermissionSetId Specifies the ID of the user-defined permission that was


created from a copy of the system permission set.

alNumberOfUserDefinedPermissionSetLinks Specifies the total number of user-defined permission sets


that are linked to system permission sets.

See common custom dimensions

Permission set link removed


Occurs when a user-defined permission set, which is linked to a system permission set, is deleted.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Permission set link removed


{alSourcePermissionSetId} ->
{alLinkedPermissionSetId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E29

alSourcePermissionSetId Specifies the ID of the system permission set that the


deleted user-defined permission set was linked to.

alLinkedPermissionSetId Specifies the ID of the deleted user-defined permission set.

alNumberOfUserDefinedPermissionSetLinks Specifies the total number of user-defined permission sets


that are linked to system permission sets.

See common custom dimensions


Permission set assigned to user
Occurs when a permission set is assigned to a user.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Permission set assigned to user : {alPermissionSetId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E2C

alPermissionSetId Specifies the ID of the permission set that was assigned to a


user.

See common custom dimensions

Permission set removed from user


Occurs when a permission set is removed from a user.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Permission set removed from user :


{alPermissionSetId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E2D

alPermissionSetId Specifies the ID of the permission set that was removed from
the user.

See common custom dimensions

Permission set assigned to user group


Occurs when a permission set is assigned to a user group.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Permission set assigned to user group:


{alPermissionSetId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E2E

alPermissionSetId Specifies the ID of the permission set that was assigned to


the user group.

alUserGroupId Specifies the ID of the user group that the permission set
was assigned to.

See common custom dimensions

Permission set removed from user group


Occurs when a permission set is removed from a user.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Permission set removed from user group:


{alPermissionSetId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000E2F

alPermissionSetId Specifies the ID of the permission set that was removed from
the user group.

alUserGroupId Specifies the ID of the user group that the permission set
was removed from.

See common custom dimensions

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Permission Dependency Cycle Trace
Telemetry
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 1 and later

A permission dependency cycle occurs when a permission set depends on itself, which can happen when you
build permissions sets that include other permission sets. For example, suppose you create a permission set Y
that includes permission set X. If you then try modify permission set X to include permission set Y, you'll create a
dependency cycle. When you create a permission dependency cycle in the Business Central client, you'll get an
error similar to the following message:
The permission set [XX] has a circular reference on path [XX]->[YY]->[XX].
This telemetry data let's you identify and analyze permission problems that users may experience in Business
Central.

Dependency cycle discovered in permission sets


Occurs when there's permission set dependency cycle in the application.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Dependency cycle discovered in permission sets

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId RT0032

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

alObjectId Specifies the ID of the object causing the dependency cycle.


If there's no value or the value is 0, then the error wasn't
related to a specific object, which typically happens when
permissionArea is something other than Object .

alObjectType The type of the AL object that the user was trying to access,
like a table or page.

clientType Specifies the type of client that opened the session, such as
Background or Web . For a list of the client types, see
ClientType Option Type.
DIM EN SIO N DESC RIP T IO N O R VA L UE

companyName The current company name.

component Dynamics 365 Business Central Ser ver

componentVersion The version number of the component that emits telemetry


(see the component dimension)

environmentName The name of the tenant environment. See Managing


Environments. This dimension isn't included for Business
Central on-premises environments.

environmentType The environment type for the tenant, such as Production ,


Sandbox, Trial. See Environment Types

permissionArea The area that the dependency cycle is related to. Possible
values include: System , Entitlement , Company , Object
.

permissionType The permission that the dependency cycle pertains to.


Possible values: Delete , Execute , Insert , Modify ,
Read , Undefined

telemetrySchemaVersion The version of the Business Central telemetry schema.

See also
Composing Permission Sets
Upgrading Extensions
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Permission Error Trace Telemetry
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 1 and later

When a user gets an error dialog about lack of permissions while working in Business Central, a telemetry
signal is emitted. This signal can be logged in an Application Insights resource.
This telemetry data let's you identify and analyze permission problems that users may experience in Business
Central.

Permission Error Shown


Occurs when a user gets a permissions-related error message in Business Central when they try to do an
operation in the application.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Permission error shown

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId RT0031

aadTenantId The Azure Active Directory (Azure AD) tenant ID that's used
for Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

alObjectId If there's no value or the value is 0, then the permission error


wasn't related to a specific object, which typically happens
when permissionArea is something other than Object .

alObjectType The type of the AL object that the user was trying to access,
like a table or page.

clientType The type of client that executed the SQL Statement, such as
Background or Web . For a list of the client types, see
ClientType Option Type.

companyName The display name of the Business Central company that was
used at time of execution

component Dynamics 365 Business Central Ser ver


DIM EN SIO N DESC RIP T IO N O R VA L UE

componentVersion The version number of the component that emits telemetry


(see the component dimension)

environmentName The name of the tenant environment. See Managing


Environments. This dimension isn't included for Business
Central on-premises environments.

environmentType The environment type for the tenant, such as Production ,


Sandbox, Trial. See Environment Types

permissionArea The area that the permission error is related to. Possible
values include: System , Entitlement , Company , Object
.

permissionType The permission that the operation requires, but the user
lacks. Possible values: Delete , Execute , Insert ,
Modify , Read , Undefined

telemetrySchemaVersion The version of the Business Central telemetry schema.

See also
Upgrading Extensions
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Profile Configuration Lifecycle Telemetry
2/6/2023 • 7 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 2, version 21.0, and later
From the Business Central Web client, users can do various operations on profiles, like, import/export, create,
copy, and remove. To learn more about these operations, see Manage User Profiles and Customize Pages for
Profiles.
Business Central emits telemetry signals for these operations, which you can collect using an Application
Insights resource. As a partner or consultant, this information gives you insight into what the service does with
the profiles and page customizations you provide.

Common custom dimensions


The following table explains custom dimensions that are common to all profile configuration traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

companyName The name of the company where the operation is applied.


Added in version 20.0.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Profile import succeeded


Occurs when a profile was successfully imported from a file.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Profile impor t succeeded: {profileId} in


app/extension {profileAppId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0046

diagnostics List of diagnostics (severity and message) from compiler and


designer.

profileAppId Specifies the ID of the extension that included the profile. An


empty value or 00000000-0000-0000-0000-000000000000
indicates the profile was created from the Business Central
web client or programmatically using AL code.

profileId Specifies the ID of the profile that was targeted by the


operation.

sqlExecutes Specifies the number of SQL statements that executed by


the operation.

serverExecutionTime Specifies the amount of time the operation took on server.


The time has the format hh:mm:ss.sssssss.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements during the operation.

result Success

totalTime Specifies the total time the operation ran for.

Profile import failed


Occurs when a profile failed to be imported from a file.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Profile impor t failed: {ProfileId} in app/extension


{ProfileAppId}

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0047

diagnostics List of diagnostics (severity and message) from compiler and


designer.

failureReason Specifies why the import operation failed.


DIM EN SIO N DESC RIP T IO N O R VA L UE

profileAppId Specifies the ID of the extension that included the profile. An


empty value or 00000000-0000-0000-0000-000000000000
indicates the profile was created from the Business Central
web client or programmatically using AL code.

profileId Specifies the ID of the profile that was targeted by the


operation.

See common custom dimensions

Profile export succeeded


Occurs when a profile was successfully exported to a file.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Profiles expor ted successfully

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0048

diagnostics List of diagnostics (severity and message) from compiler and


designer.

force Species whether the Force flag was set, allowing to export
profiles even with compilation errors.

sqlExecutes Specifies the number of SQL statements that executed by


the operation.

serverExecutionTime Specifies the amount of time the operation took on server.


The time has the format hh:mm:ss.sssssss.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements during the operation.

result Success

totalTime Specifies the total time the operation ran for.

See common custom dimensions

Profiles export failed


Occurs when a profile failed to be exported to a file.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Profiles failed to be expor ted

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0049

diagnostics List of diagnostics (severity and message) from compiler and


designer.

failureReason Specifies why the export operation failed.

See common custom dimensions

Profile copy succeeded


Occurs when a profile was copied successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Profile copy succeeded: {profileId} to {newProfileId}


from app/extension {profileAppId} to app/extension
{newProfileAppId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0050

diagnostics List of diagnostics (severity and message) from compiler and


designer.

ProfileAppId Specifies the ID of the extension that included the profile


that was copied. An empty value or
00000000-0000-0000-0000-000000000000 indicates the
profile was created from the Business Central web client or
programmatically using AL code.

ProfileId Specifies the ID of the profile that was copied.


DIM EN SIO N DESC RIP T IO N O R VA L UE

newProfileAppId Specifies the ID of the extension that included the new


profile. An empty value or
00000000-0000-0000-0000-000000000000 indicates the
profile was created from the Business Central web client or
programmatically using AL code.

newProfileId Specifies the ID of the new profile that was created from a
copy.

sqlExecutes Specifies the number of SQL statements that executed by


the operation.

serverExecutionTime Specifies the amount of time the operation took on server.


The time has the format hh:mm:ss.sssssss.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements during the operation.

result Success

totalTime Specifies the total time the operation ran for.

See common custom dimensions

Profile copy failed


Occurs when a profile failed to copy successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Profile copy failed: {ProfileId} to {NewProfileId} from


app/extension {ProfileAppId} to app/extension
{NewProfileAppId}

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0051

diagnostics List of diagnostics (severity and message) from compiler and


designer.

failureReason Specifies why the copy operation failed.


DIM EN SIO N DESC RIP T IO N O R VA L UE

profileAppId Specifies the ID of the extension that included the profile


that was copied. An empty value or
00000000-0000-0000-0000-000000000000 indicates the
profile was created from the Business Central web client or
programmatically using AL code.

profileId Specifies the ID of the profile that was copied.

newProfileAppId Specifies the ID of the extension that included the new


profile. An empty value or
00000000-0000-0000-0000-000000000000 indicates the
profile was created from the Business Central web client or
programmatically using AL code.

newProfileId Specifies the ID of the new profile that was created from a
copy.

See common custom dimensions

Profile created successfully


Occurs when a new profile was created successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Profile created successfully: {profileId} in


app/extension {profileAppId}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0052

profileAppId Specifies the ID of the extension that includes the new


profile. An empty value or
00000000-0000-0000-0000-000000000000 indicates the
profile was created from the Business Central web client or
programmatically using AL code.

profileId Specifies the ID of the profile that was created.

See common custom dimensions

Profile removed
Occurs when a profile was deleted.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Profile removed: {profileId} in app/extension


{profileAppId}

severityLevel 2

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0053

profileAppId Specifies the ID of the extension that included the profile


that was removed. An empty value or
00000000-0000-0000-0000-000000000000 indicates the
profile was created from the Business Central web client or
programmatically using AL code.

profileId Specifies the ID of the profile that was removed.

See common custom dimensions

Profile page customization removed


Occurs when a page customization was deleted from a profile.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Profile page customization removed: {profileId} in


app/extension {profileAppId}

severityLevel 2

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0054

pageId Specifies the ID of the page object from which the


customization was removed.

profileAppId Specifies the ID of the extension that included the profile


page customization that was removed. An empty value or
00000000-0000-0000-0000-000000000000 indicates the
profile was created from the Business Central web client or
programmatically using AL code.

profileId Specifies the ID of the profile that was targeted by the


operation.

See common custom dimensions


Profile page customization converted
Occurs when a page customization was converted successfully.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Profile page customization conver ted: {ProfileId} in


app/extension {ProfileAppId}

severityLevel 2

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0055

pageId Specifies the ID of the page object for which the


customization was converted.

profileAppId Specifies the ID of the extension that included the profile


page customization. An empty value or
00000000-0000-0000-0000-000000000000 indicates the
profile was created from the Business Central web client or
programmatically using AL code.

profileId Specifies the ID of the profile that was targeted by the


operation.

operationReason Specifies the reason why the conversion was triggered.

See common custom dimensions

Next steps
Use this telemetry data to determine how the users are working with the profiles that you provide in extensions.
Then, make changes to better suit the users needs as you see fit.

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Report Telemetry
2/6/2023 • 12 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1

Report telemetry gathers data about which reports are run on the environment. It provides information about
whether the report succeeded, failed, or was canceled. For each report, it tells you how long it ran, how many
SQL statements it executed, and how many rows it consumed.
You use this data to gather statistics on report usage or to help identify slow-running reports.

Successful report generation


Occurs when a report dataset generates without any errors.
General dimensions
The following table explains the general dimensions of this trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

operation_Name Success repor t generation

Note: The use of the operation_Name column was


deprecated in version 16.1. In future versions, data won't be
stored in this column. So in version 16.1 and later, use the
custom dimension column eventID column custom in
Kusto queries instead of operation_Name .

message Version 16.1 and later:


Repor t rendered: {repor t ID} - {repor t name}

Before version 16.1:


The repor t {repor t ID} '{repor t name}' rendered
successfully

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alObjectId Specifies the ID of the report object that was run.

alObjectName Specifies the name of the report object that was run.

alObjectType Repor t .

alStackTrace The stack trace in AL.


DIM EN SIO N DESC RIP T IO N O R VA L UE

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company


for which the report was run.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

documentFormat Specifies the format of the report outputs as a result of the


report action. See documentFormat. This dimension was
added in version 20.0.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId RT0006

This dimension was introduced in Business Central 2020


release wave 1, version 16.1.

extensionId Specifies the appID of the extension that the report object
belongs to.

extensionName Specifies the name of the extension that the report object
belongs to.

extensionVersion Specifies the version of the extension that the report object
belongs to.

numberOfRows Specifies the number of rows/records generated for the


report dataset.

reportAction Specifies the action that was done on the report. See
reportAction. This dimension was added in version 20.0.

reportingEngine Specifies the reporting engine used to generate the report,


such as ProcessingOnly , Rdlc, or Word . This dimension
was added in version 17.3

result Success
DIM EN SIO N DESC RIP T IO N O R VA L UE

serverExecutionTime Specifies the amount of time it took the service to complete


the request[1]. The time has the format hh:mm:ss.sssssss.

sqlDatabaseAccessIntent Specifies the database access intent used to read data for
the report, such as ReadOnly , or ReadWrite . This
dimension was added in version 19.1.

sqlExecutes Specifies the number of SQL statements that the report


executed[1].

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements[1].

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time it took for the system to


generate the dataset and render the report[1]. The time has
the format hh:mm:ss.sssssss.

1From telemetrySchemaVersion 0.6 and onwards, this value also includes the CompanyOpen operation.
reportAction
The reportAction dimension shows actions taken to generate a report. The action can be taken from the report
request page, for example, from the Send To menu, or from AL code.

VA L UE DESC RIP T IO N

None There were no results from the request page, for example,
the user canceled.

Print The user selected to print the report.

Preview The user selected to preview the report from the request
page.

Save The report was saved to a file by a call to the SaveAs


method in AL code.

Schedule The user selected to schedule the report from the request
page.

Download The user downloaded the report as a file from the request
page.

Parameters Parameters and filters were collected from the request page
without rendering the output.

documentFormat
The documentFormat dimension shows the output of the generated report as a result of the report action. The
action can be taken from the report request page, for example, from the Send To menu, or from AL code.
VA L UE DESC RIP T IO N

None There was no output, for example, the user canceled.

Rdlc The output was a .rdlc file type.

Word The output was a .docx file type.

Excel The output was a .xlsx file type that included the layout and
dataset.

ExcelDataset The output was a .xlsx file type that contained the dataset
only.

Custom The output was an custom file type.

ProcessingOnly The action was for processing report without any kind of
layout.

Failed report generation


This operation occurs when the report dataset couldn't be generated because of an error.
General dimensions
The following table explains the general dimensions of the Failed repor t generation operation.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Version 16.1 and later:


Repor t rendering failed: {repor t ID} - {repor t name}

Before version 16.1:


The repor t {repor t ID} '{repor t name}' couldn't be
rendered

operation_Name Failed repor t generation

Note: The use of the operation_Name column was


deprecated in version 16.1. In future versions, data won't be
stored in this column. So in version 16.1 and later, use the
custom dimension column eventID column custom in
Kusto queries instead of operation_Name .

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alObjectId Specifies the ID of the report object that was run.


DIM EN SIO N DESC RIP T IO N O R VA L UE

alObjectName Specifies the name of the report object that was run.

alObjectType Repor t .

alStackTrace The stack trace in AL.

cancelReason[2] Specifies why the report was canceled.

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company


for which the report was run.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

documentFormat Specifies the format of the report outputs as a result of the


report action. See documentFormat. This dimension was
added in version 20.0.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId RT0006

This dimension was introduced in Business Central 2020


release wave 1, version 16.1.

extensionId Specifies the appID of the extension that the report object
belongs to.

extensionName Specifies the name of the extension that the report object
belongs to.

extensionVersion Specifies the version of the extension that the report object
belongs to.

numberOfRows Specifies the number of rows/records generated for the


report dataset.
DIM EN SIO N DESC RIP T IO N O R VA L UE

reportAction Specifies the action that was done on the report. See
reportAction. This dimension was added in version 20.0.

reportingEngine Specifies the reporting engine used to generate the report,


such as ProcessingOnly , Rdlc, or Word . This dimension
was added in version 17.3

result Specifies the title of the exception that was thrown, such as
NavNCLDialogException .

serverExecutionTime Specifies the amount of time used by service on the request.


The time has the format hh:mm:ss.sssssss.

sqlExecutes Specifies the number of SQL statements that the report


executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

totalTime Specifies the amount of time used to generate the dataset


and render the report before it failed. The time has the
format hh:mm:ss.sssssss.

2 Available in Business Central 2020 release wave 2 and later only.


Analyzing report generation failures
When a report fails to generate, the result column in the CustomDimensions will include the title of the
exception that was thrown by the service or the AL code.

Cancellation report generation


This operation occurs when the report dataset generation was canceled. There are various conditions that can
cancel a report. The Cancellation repor t generation operation emits different trace messages for each
condition.
General dimensions
The following table explains the general dimensions of the Cancellation repor t generation operation.

DIM EN SIO N DESC RIP T IO N O R VA L UE

operation_Name Cancellation repor t generation

Note: The use of the operation_Name column was


deprecated in version 16.1. In future versions, data won't be
stored in this column. So in version 16.1 and later, use the
custom dimension column eventID column custom in
Kusto queries instead of operation_Name .

message Specifies the reason why the report was canceled. See
Analyzing cancellation messages section for details.
DIM EN SIO N DESC RIP T IO N O R VA L UE

severityLevel 2

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alObjectId Specifies the ID of the report object that was run.

alObjectName Specifies the name of the report object that was run.

alObjectType Repor t .

alStackTrace The stack trace in AL.

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company


for which the report was run.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId RT0007

This dimension was introduced in Business Central 2020


release wave 1, version 16.1.

extensionId Specifies the appID of the extension that the report object
belongs to.

extensionName Specifies the name of the extension that the report object
belongs to.
DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionVersion Specifies the version of the extension that the report object
belongs to.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Analyzing report cancellations


The cancellation messages indicate events that caused the report to be canceled. The telemetry can help identify
slow-running reports - reports that take longer than expected to run and generate a large number of rows.

NOTE
The service evaluates cancellation events in a specific order, and the evaluation is done every five seconds. For more
information, see Report Generation and Cancellation Flow.

Cancellation event received. Requesting cancellation of the action.


This message occurs when the session canceled a report as it was being generated.
Received a cancellation request from the user. Requesting cancellation of the action.
This message occurs when a user canceled a report in the client as it was being generated.
The action took longer to complete ({0}) than the specified threshold ({1}). Requesting cancellation of the action.
The service is configured to cancel reports if they take longer to generate than a set amount of time. With
Business Central online, you can't change the threshold. With Business Central on-premises, you change the
threshold by setting the Max Execution Timeout parameter on the Business Central Server instance. There's
no timeout for on-premises by default. For more information, see Configuring Business Central Server.
The rendering of the word report has been cancelled because it took longer than the specified threshold ({0})"
This message occurs when a report that based on a Word layout takes longer to generate than the specified
threshold. The event is only relevant for Business Central online. There's no timeout for on-premises.
The number of processed rows exceeded ({0} rows ) the maximum number of rows ({1} rows ). Requesting cancellation of the action.
The service is configured to cancel reports if they generate more than a set number of rows. With Business
Central online, you can't change this threshold. With Business Central on-premises, you change the threshold by
setting the Max Rows parameter on the Business Central Server instance. There's no limit on rows for on-
premises by default. For more information, see Configuring Business Central Server.

Report cancelled but a commit occurred


This operation occurs when the report dataset generation was canceled but a COMMIT operation occurred
before the cancellation. This pattern isn't recommended. Reconsider the report design.
General dimensions
The following table explains the general dimensions of the Repor t cancelled but a commit occurred
operation.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message The report <ID> '<Name>' is being canceled, but a


COMMIT() has been performed. This can lead to data
inconsistency if the report is not idempotent

severityLevel 2
Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alObjectId Specifies the ID of the report object that was run.

alObjectName Specifies the name of the report object that was run.

alObjectType Repor t .

alStackTrace The stack trace in AL.

cancelReason The reason why the report was cancelled

clientType Specifies the type of client that executed the SQL Statement,
such as Background or Web . For a list of the client types,
see ClientType Option Type.

companyName Specifies the display name of the Business Central company


for which the report was run.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId RT0011

This dimension was introduced in Business Central 2020


release wave 1, version 16.1.

extensionId Specifies the appID of the extension that the report object
belongs to.

extensionName Specifies the name of the extension that the report object
belongs to.

extensionPublisher Specifies the name of the extension publisher that the report
object belongs to.
DIM EN SIO N DESC RIP T IO N O R VA L UE

extensionVersion Specifies the version of the extension that the report object
belongs to.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Retention Policy Trace Telemetry
2/6/2023 • 4 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2, update 17.1 and later
Administrators define retention policies to specify how frequently they want Business Central to delete outdated
data in tables that contain log entries and archived records. For example, cleaning up log entries makes it easier
to work with the data that's relevant. Policies can include all data in the tables that is past the expiration date. Or
you can add filter criteria to include only certain expired data in the policy.
To gather this telemetry data, you'll have to set up retention policies on tables that contain log entries and
archived records. For more information, see Define Retention Policies in the Application help.
Telemetry is then logged for the following operations:
A table is added to the list of allowed tables
An error occurs when adding a new retention policy
A retention policy is enabled
A retention policy is applied, either manually or automatically
Data is deleted because of a retention policy
The first retention policy is enabled on a table in a company
The last retention policy is removed in a company

Retention policy log entry logged


Occurs when a retention policy is enabled, applied, or disabled. It provides information about the different
operations related to the retention policy. This information is similar to what you see in the Retention Policy
Log page in the client.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Retention Policy Log Entr y Logged: {alMessageType}

severityLevel 1 for error, 2 for warning, 3 for info

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000D3L

alCategory Specifies the aspect of the retention policy that created the
log entry. For example, it can be related to setup, the
retention period, and when the policy was applied. Some of
the values are: Retention Policy - Setup , Retention
Policy - Apply , Retention Policy - Schedule , Retention
Policy - Allowed Tables .

alCompanyName Specifies the Business Central company that the retention


policy applies to.
DIM EN SIO N DESC RIP T IO N O R VA L UE

alLogEntry Specifies message about the retention policy execution step,


for example: Table 405 Change Log Entry was added to the
list of allowed tables. Default Date Field No.: 2000000001

alMessageType Specifies the message type for the log entry:


Error - indicates an error occurred and the operation
was unsuccessful
Warning - indicates that the operation succeeded
but there's a warning
Info - indicates that the operation was successful.

Common custom dimensions


The following table explains other custom dimensions that are common to all retention policy traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentName Specifies the name of the tenant environment. See


Managing Environments. This dimension isn't included for
Business Central on-premises environments.

alDataClassification SystemMetadata

alObjectId 3912 , which is the ID of the Reten. Policy Telemetr y


Impl. codeunit.

alObjectName Reten. Policy Telemetr y Impl.

alObjectType Codeunit

extensionId Specifies the ID of the system application: 63ca2fa4-4f03-


4f2b-a480-172fef340d3f .

extensionName System Application

extensionVersion Specifies the version of the system application.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.
Records deleted using retention policy
Occurs when a record is deleted by a retention policy.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Records Deleted Using Retention Policy: Deleted


{alRecordsDeleted} records from Table {alTableNo},
{alTableName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000D6H

alCompanyName Specifies the Business Central company that the retention


policy applies to.

alManualRun Specifies whether the retention policy was run manually,


true , or automatically by a job queue entry, false .

alRecordsDeleted Specifies the number of records that were deleted by the


retention policy.

alTableName Specifies the name of the table from which the records were
deleted.

alTableNo Specifies the ID of the table from which the records were
deleted.

See common custom dimensions

First retention policy enabled on company


Occurs when the first retention policy is enabled in a company.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message First retention policy enabled on: {alCompanyName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000D6I
DIM EN SIO N DESC RIP T IO N O R VA L UE

alCompanyName Specifies the Business Central company that the retention


policy applies to.

alTableName Specifies the name of the table the retention policy was
enabled on.

alTableNo Specifies the ID of the table that the retention policy was
enabled on.

See common custom dimensions

Last retention policy disabled on company


Occurs when the last retention policy is disabled in a company.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Last retention policy disabled on: {alCompanyName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId AL0000D6J

alCompanyName Specifies the Business Central company that the retention


policy applies to.

alTableName Specifies the name of the table from which the records were
deleted.

alTableNo Specifies the ID of the table from which the records were
deleted.

See common custom dimensions

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Stopped Session Telemetry
2/6/2023 • 2 minutes to read • Edit Online

In Business Central, a background session is session without a UI that runs a specified codeunit. Background
sessions are started and stopped by calling the StartSession and StopSession methods from AL. With Business
Central online, sessions can be stopped by using the admin center, which indirectly calls the StopSession
method. For more information, see Managing Sessions.
With Application Insights, you can record when sessions are stopped, either by direct calls to the StopSession
method or from the admin center.

The StopSession method was invoked on session


A session was stopped by a direct call to the StopSession method from AL or from the admin center.
General dimensions
This table explains the columns included in trace emitted when a session is stopped.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message The StopSession method was invoked on session


{stoppingSessionID}

operation_Name StopSessionOperation

severityLevel 1

CustomDimensions
The following table describes the most relevant custom dimensions of the trace.

C O L UM N DESC RIP T IO N O R VA L UE

eventId RT0029

alObjectId* The ID of the object that called the StopSession method to


cancel the session

alObjectName* The name of the object that called the StopSession method
to cancel the session

alObjectType* The type of the object, like codeunit or page, called by the
StopSession method to cancel the session

alStackTrace* The stack trace for the session stop in AL.

cancellationComment The comment defined in the StopSession method call.


Stopped by management PowerShell cmdlet means
that the session was stopped from the Business Central
admin center.
C O L UM N DESC RIP T IO N O R VA L UE

clientType The type of client that called the Stop Session method such
as Background , WebClient , or ManagementClient .
ManagementClient indicates that the session was
canceled from the Business Central admin center. For a list of
the client types, see ClientType Option Type.

companyName* The name of the company that was open during the session

currentSessionID The ID of the session that called the StopSession method to


stop the session identified by stoppingSessionID .

extensionName The name of the extension that included the code that called
the StopSession method.

result The return value of the StopSession method call.

stoppingSessionID The ID of the session that was stopped by the StopSession


method call

stoppingSessionIsAdmin Indicates whether the session that was stopped was running
as an administrator

See common custom dimensions

Not shown for sessions canceled from the admin center.


Other custom dimensions
The following table explains other custom dimensions os the trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId The Azure Active Directory (Azure AD) tenant ID that's used
for Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

component Dynamics 365 Business Central Ser ver

componentVersion The version number of the component that emits telemetry


(see the component dimension)

environmentName The name of the tenant environment. See Managing


Environments. This dimension isn't included for Business
Central on-premises environments.

environmentType The environment type for the tenant, such as Production ,


Sandbox, Trial. See Environment Types

telemetrySchemaVersion The version of the Business Central telemetry schema

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Monitoring and Analyzing Long Running SQL Queries On-Premises
The Business Central Administration Center
Analyzing Table Index Trace Telemetry
2/6/2023 • 3 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1, version 18.0 and later
The table index trace gathers data when a index is added to, modified, or removed from a base table by a table
extension.
In AL, an index is defined by a key, which can include one or more table fields. A key in a table extension object
can include either fields from the base table or fields from the table extension object itself. A key that includes
base tables fields is added as an index on the base table in the SQL database. For more information, see Table
Keys.
This signal is emitted when a table extension object is installed or upgraded on a tenant, and it does one of the
following operations:
Adds an index to the base table
Changes an existing index on the base table, for example, it adds or removes fields
Removes an existing index from the base table

Index enabled
Occurs when an index was added or modified on the base table by key in a table extension object.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Index enabled: {alObjectName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0024

alObjectId Specifies the ID of table that the index was added or


changed.

alObjectName Specifies the name of table that the index was added or
changed.

extensionId Specifies the ID of the extension that added the index.

extensionName Specifies the name of the extension that added or changed


the index.

extensionPublisher Specifies the publisher of the extension that added added or


changed the index.
DIM EN SIO N DESC RIP T IO N O R VA L UE

keyMaintainSIFTIndex Specifies whether the index's MaintainSIFTIndex property is


true or false .

keyMaintainSQLIndex Specifies whether the index's MaintainSQLIndex property is


true or false .

keyFields Specifies the table fields that are included in the index.

keyName Specifies the name of the index that was added or changed.

Common custom dimensions


The following table explains other custom dimensions that are common to all table index traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys Specifies a comma-separated list of all the keys that have


been deprecated. The keys in this list are still supported but
will eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

environmentName Specifies the name of the tenant environment. See


Managing Environments. This dimension isn't included for
Business Central on-premises environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Index disabled
Occurs when an index was removed from the base table by table extension object.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message Index disabled: {alObjectName}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0025

alObjectId Specifies the ID of table that the index was removed from.

alObjectName Specifies the name of table that the index was removed
from.

extensionId Specifies the ID of the extension that removed the index.

extensionName Specifies the name of the extension that removed the index.

extensionPublisher Specifies the publisher of the extension that removed the


index.

keyMaintainSIFTIndex Specifies whether the index's MaintainSIFTIndex property


was true or false .

keyMaintainSQLIndex Specifies whether the index's MaintainSQLIndex property


was true or false .

keyFields Specifies the table fields that are included in the index.

keyName Specifies the name of the index that was removed.

See common custom dimensions

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Task Scheduler Telemetry
2/6/2023 • 9 minutes to read • Edit Online

INTRODUCED IN: Business Central 2021 release wave 2

Task scheduler telemetry gathers information about the execution of scheduled tasks. The data gives insight into
what happens in background sessions that are coming from scheduled tasks. It provides information that let's
you troubleshoot failures. The data can also help you determine whether tasks would be better scheduled for off
hours to limit the load on the service.
For an overview of task scheduler to understand the flow related to these traces, see Task Scheduler.

NOTE
In this article, main codeunit refers to the codeunit that's run by the TaskScheduler.CreateTask method.

Each scheduled task is assigned a unique identifier (ID), which is included in each trace related to the task. Using
the ID makes it easy to query the flow of a task.

Task created
Occurs when a task was created by a TaskScheduler.CreateTask method call in AL code.
General dimensions
The following table explains the general dimensions of this trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Task {taskId} created: {codeunitObjectId} scheduled


to run after {notBefore}. Ready to run: {isReady}

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0040

codeunitObjectId Specifies the ID of the task's main codeunit.

failureCodeunitObjectId Specifies the ID of the task's failure codeunit. 0 indicates that


there's no failure codeunit.

isReady Specifies whether the task was in the the ready state when
created. True indicates that the task is in the ready state.
False indicates that the task isn't in the ready state.

notBefore Specifies the earliest date and time the task was scheduled
to run.
DIM EN SIO N DESC RIP T IO N O R VA L UE

taskId Specifies the unique identifier assigned to the task.

timeout Specifies the timeout that was set on the task. If a task takes
longer to complete than the specified time, it's canceled. The
time has the format hh:mm:ss.sssssss.

Common custom dimensions


The following table explains other custom dimensions that are common to all task scheduler traces.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

companyName Specifies the display name of the Business Central company


in which the task was run.

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

formatId Specifies the regional setting of the session. The value is a


culture identifiers (LCIDs), such as 1033 for English - United
States.

languageId Specifies the language version of Business Central on which


the task is run. The value is a culture identifiers (LCIDs), such
as 1033 for English - United States.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Task ready
Occurs when a task is set to the ready state by TaskScheduler.SetTaskReady method call in AL code. A task can't
be run until it's in the ready state.
General dimensions
The following table explains the general dimensions of this trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Task {taskId} ready: {codeunitObjectId} set ready to


run after {notBefore}.

severityLevel 1
Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0041

codeunitObjectId Specifies the ID of the task's main codeunit.

failureCodeunitObjectId Specifies the ID of the task's failure codeunit. 0 indicates that


there's no failure codeunit.

isReady True

notBefore Specifies the earliest date and time that was scheduled to
run.

taskId Specifies the unique identifier assigned to the task.

timeout Specifies the timeout that was set on the task. If a task takes
longer to complete than the specified time, it's canceled. The
time has the format hh:mm:ss.sssssss.

See common custom dimensions

Task removed
Occurs when a task is deleted by a TaskScheduler.CancelTask method call in AL code.
General dimensions
The following table explains the general dimensions of this trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Task {taskId} removed: {codeunitObjectId}.

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0042

codeunitObjectId Specifies the ID of the task's main codeunit.

failureCodeunitObjectId Specifies the ID of the task's failure codeunit. 0 indicates that


there's no failure codeunit.

isReady Specifies whether the task was in the ready state when
removed. True indicates that the task was in the ready state.
False indicates that the task wasn't in the ready state.

notBefore Specifies the earliest date and time that was scheduled to
run.
DIM EN SIO N DESC RIP T IO N O R VA L UE

taskId Specifies the unique identifier assigned to the task.

timeout Specifies the timeout that was set on the task. The time has
the format hh:mm:ss.sssssss.

See common custom dimensions

Task canceled
Occurs when the execution of a task's main or failure codeunit is canceled by the service or by a user.
For example, the service cancels a task when:
It takes longer to complete than the specified timeout. The timeout is specified on the task when it's created.
Or if no timeout is specified, then the default timeout of the service is used. For online, the default task
timeout is 12 hours. For on-premises, the default timeout is specified by the Default Task Scheduler
Session Timeout setting on the Business Central Server instance.
The Session.StopSession method was called from AL code.
Users can cancel a task a couple ways. For example, with Business Central online, they can use the Business
Central admin center. With on-premises, they can run the the Remove-NAVSession cmdlet.
General dimensions
The following table explains the general dimensions of this trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE


DIM EN SIO N DESC RIP T IO N O R VA L UE

message The messages will depend on whether the error occurred in


the main codeunit ot failure codeunit.

Main codeunit
Task {taskId} main codeunit {codeunitObjectId}
canceled. It will not be retried and the failure
codeunit {failureCodeunitObjectId} will be run.
Reason: Exception is not retriable.

Task {taskId} main codeunit {codeunitObjectId}


canceled. It will be retried. Reason: Exception is
retriable.

Task {taskId} main codeunit {codeunitObjectId}


canceled. It will not be retried. Reason: Exception is
retriable but the maximum number of attempts has
been reached.

Failure codeunit
Task {taskId} failure codeunit
{failureCodeunitObjectId} canceled. It will not be
retried. Reason: Exception is not retriable.

Task {taskId} failure codeunit


{failureCodeunitObjectId} canceled. It will be retried.
Reason: Exception is retriable.

Task {taskId} failure codeunit


{failureCodeunitObjectId} canceled. It will not be
retried. Reason: Exception is retriable but the
maximum number of attempts has been reached.

severityLevel 2

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0044

attemptNumber Specifies the run attempt on the codeunit. 0 indicates the


first run of the codeunit. Any value other than 0 indicates a
retry.

cancelReason Specifies why the task was canceled.

cancelReasonMessage Specifies the exception that caused the cancellation.

codeunitObjectId Specifies the ID of the task's main codeunit.

failureCodeunitObjectId Specifies the ID of the task's failure codeunit. 0 indicates that


there's no failure codeunit.

isReady True

notBefore Specifies the earliest date and time to the task was
scheduled to run.
DIM EN SIO N DESC RIP T IO N O R VA L UE

result Canceled

serverExecutionTime Specifies the amount of time it took the server to run the
codeunit. The time has the format hh:mm:ss.sssssss.

sessionId Specifies the unique identifier of the session in which the


task's codeunit was run.

sqlExecutes Specifies the number of SQL statements that were executed


by the codeunit before the task was canceled.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements before the task was canceled.

taskId Specifies the unique identifier assigned to the task.

timeout Specifies the timeout that was set on the task. The time has
the format hh:mm:ss.sssssss.

totalTime Specifies the amount of time it took before the task was
canceled. The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Task failed
Occurs when the execution of task's main codeunit or failure codeunit fails because of an exception.
General dimensions
The following table explains the general dimensions of this trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE


DIM EN SIO N DESC RIP T IO N O R VA L UE

message The messages will depend on whether the error occurred in


the main codeunit ot failure codeunit.

Main codeunit
Task {taskId} main codeunit {codeunitObjectId}
failed. It will not be retried and the failure codeunit
{failureCodeunitObjectId} will be run. Reason:
Exception is not retriable.

Task {taskId} main codeunit {codeunitObjectId}


failed. It will be retried. Reason: Exception is
retriable.

Task {taskId} main codeunit {codeunitObjectId}


failed. It will not be retried. Reason: Exception is
retriable but the maximum number of attempts has
been reached.

Failure codeunit
Task {taskId} failure codeunit {codeunitObjectId}
failed. It will not be retried. Reason: Exception is not
retriable.

Task {taskId} failure codeunit


{failureCodeunitObjectId} failed. It will be retried.
Reason: Exception is retriable

Task {taskId} failure codeunit


{failureCodeunitObjectId} failed. It will not be
retried. Reason: Exception is retriable but the
maximum number of attempts has been reached.

severityLevel 3

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0045

attemptNumber Specifies the retry attempt on the codeunit. 0 indicates the


initial run of the codeunit, not a retry.

codeunitObjectId Specifies the ID of the task's main codeunit.

failureCodeunitObjectId Specifies the ID of the task's failure codeunit. 0 indicates that


there's no failure codeunit.

failureReason Specifies the exception that thrown as a result of the error.

isReady Specifies whether the task is in the ready state. True


indicates that the task is in the ready state. False indicates
that the task isn't in the ready state.

notBefore Specifies the earliest date and time that was scheduled to
run.
DIM EN SIO N DESC RIP T IO N O R VA L UE

result Failure

serverExecutionTime Specifies the amount of time it took the server to run the
codeunit. The time has the format hh:mm:ss.sssssss.

sessionId Specifies the unique identifier of the session in which the


task's codeunit was run.

sqlExecutes Specifies the number of SQL statements that were executed


before the task failed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements before the task failed.

taskId Specifies the unique identifier assigned to the task.

timeout Specifies the timeout that was set on the task. The time has
the format hh:mm:ss.sssssss.

totalTime Specifies the amount of time it took to create the company.


The time has the format hh:mm:ss.sssssss.

See common custom dimensions

Task completed
Occurs when the execution of a task's main codeunit or failure codeunit succeeds with no errors.
Note that there is no event emitted for task started. You can infer the task-start time by subtracting the totalTime
from the task completed timestamp.
General dimensions
The following table explains the general dimensions of this trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Task {taskId} main codeunit {codeunitObjectId}


completed. - This message indicates that the task was fully
executed successfully.

Task {taskId} failure codeunit


{failureCodeunitObjectId} completed. - This message
indicates that an error occurred in the task, but it was
successfully handled by the failure codeunit.

severityLevel 1

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId LC0043
DIM EN SIO N DESC RIP T IO N O R VA L UE

attemptNumber Specifies the retry attempt on the codeunit. 0 indicates the


initial run of the codeunit, not a retry.

codeunitObjectId Specifies the ID of the task's main codeunit.

failureCodeunitObjectId Specifies the ID of the task's failure codeunit. 0 indicates that


there's no failure codeunit.

isReady Specifies whether the task is in the ready state. True


indicates that the task is in the ready state. False indicates
that the task isn't in the ready state.

notBefore Specifies the earliest date and time that was scheduled to
run.

result Success

serverExecutionTime Specifies the amount of time it took the server to run the
codeunit. The time has the format hh:mm:ss.sssssss.

sessionId Specifies the unique identifier of the session in which the


task was run.

sqlExecutes Specifies the number of SQL statements that were executed.

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.

taskId Specifies the unique identifier assigned to the task.

timeout Specifies the timeout that was set on the task. The time has
the format hh:mm:ss.sssssss.

totalTime Specifies the amount of time it took to run the codeunit. The
time has the format hh:mm:ss.sssssss.

See common custom dimensions

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing User Checklist Telemetry
2/6/2023 • 2 minutes to read • Edit Online

User checklist telemetry gathers data about state changes for the checklists presented to users when
onboarding to Business Central. For more information about checklists, see Get Users Started with the Checklist.

User checklist status updated


Occurs when the checklist status changes for the environment.
General dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

message User checklist status updated: {oldStatus} to


{newStatus}

{oldStatus} indicates the old status of the checklist.

{newStatus} indicates the new status of the checklist.

Custom dimensions
DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (AAD) tenant ID used for
Azure AD authentication. For on-premises, if you aren't
using Azure AD authentication, this value is common .

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production or Sandbox. See Environment Types

eventId AL0000EIQ

alOldStatus The old status of the checklist, for example Not Star ted or
In progress .

alNewStatus The new status of the checklist, for example In progress or


Completed .

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Verbose Telemetry
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 1 and later

Business Central users can temporarily set up their environment to emit more verbose telemetry by going to
the Help and Suppor t page in the client and selecting Additional Logging . They'll typically only do this
when asked by a partner or support representative to help troubleshoot problems. This additional logging will
continue for 15 minutes or until the user closes the browser or signs out of Business Central—then it's turned
off
A telemetry trace is recorded whenever additional logging is turned on or off.
For information about enabling additional logging, see Resources for Help and Support.

Verbose telemetry enabled for session


Occurs when additional logging is turned on from the Help and Suppor t page in the client.
General dimensions
The following table explains the general dimensions included in the trace. The table lists the dimensions that are
specific to Business Central.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Verbose telemetr y enabled for session: {sessionId}

severityLevel 3

Custom dimensions
The following table explains the custom dimensions included in the trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentName Specifies the name of the tenant environment. See


Managing Environments. This dimension is only for traces
from Business Central online.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types
DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId RT0023

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Verbose telemetry disabled for session


Occurs when additional logging is turned off because a user closed the browser in which Business Central was
running or they signed out of Business Central.
General dimensions
The following table explains the general dimensions included in the trace. The table lists the dimensions that are
specific to Business Central.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Verbose telemetr y disabled for session: {sessionId}

severityLevel 3

Custom dimensions
The following table explains the custom dimensions included in the trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

eventId RT0024

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentName Specifies the name of the tenant environment. See


Managing Environments. This dimension is only for traces
from Business Central online.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Web Service Access Key Telemetry
2/6/2023 • 3 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2, version 17.3, and later
The Business Central emits telemetry data about the success or failure of authenticating web service access keys
on web service requests.

IMPORTANT
Starting October, 2022, the use of access keys (Basic Auth) for web service authentication is deprecated and not
supported in Business Central online. We recommend that you use OAuth2 instead. For more information, see Using
OAuth to Authorize Business Central Web Services.

As a partner or customer, this data lets you monitor the use of web service access keys on your environments in
preparation for the deprecation of the feature.
For information about web service access keys, see How to use an Access Key for SOAP and OData Web Service
Authentication.

Authentication with web service key succeeded


Occurs when a web service access key was authenticated successfully.
General dimensions
The following table explains the general dimensions included in the trace. The table lists the dimensions that are
specific to Business Central.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Authentication with Web Ser vice Key succeeded:


{endpoint}

severityLevel 1

Custom dimensions
The following table explains the custom dimensions included in the trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alObjectId Specifies the ID of the AL object that was run by request.

authenticationStatus Succeeded

authenticationType Specifies whether the service uses NavUserPassword or


AccessControl (Azure AD) authentication.

category Specifies the service type. Values include: Api, ODataV4 ,


ODataV3 , and SOAP .
DIM EN SIO N DESC RIP T IO N O R VA L UE

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

endpoint Specifies the endpoint for the request. Private and sensitive
information is omitted from the endpoint.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId RT0020

This dimension was introduced in Business Central 2020


release wave 1, version 16.1.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Authentication with web service key failed


Occurs when a web service access key failed to authenticate.
General dimensions
The following table explains the general dimensions included in the trace. The table lists the dimensions that are
specific to Business Central.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Authentication with Web Ser vice Key failed:


{endpoint}

severityLevel 3

Custom dimensions
The following table explains the custom dimensions included in the trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alObjectId Specifies the ID of the AL object that was run by request.

authenticationStatus Failed

authenticationType Specifies whether the service uses NavUserPassword or


AccessControl (Azure AD) authentication.
DIM EN SIO N DESC RIP T IO N O R VA L UE

category Specifies the service type. Values include: Api, ODataV4 ,


ODataV3 , and SOAP .

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

endpoint Specifies the endpoint for the request. Private and sensitive
information is omitted from the endpoint.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId RT0021

failureReason Specifies the exception that was thrown by the server. Some
exception messages can contain customer data. As a
precaution, Business Central only emits information that's
classified as SystemMetadata. Exception messages that
contain other data classifications, like customer data, are not
shown. Instead, the following message is shown: "Message
not shown because the NavBaseException(string, Exception,
bool) constructor was used."

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Example trace
The following code snippet is a CustomDimensions example:
{"component":"Dynamics 365 Business Central
Server","category":"Api","AadTenantId":"common","environmentType":"Production","Component":"Dynamics 365 Business Central
Server","AL Object Id":"0","alObjectId":"0","Telemetry schema
version":"0.1","telemetrySchemaVersion":"0.1","authenticationType":"NavUserPassword","componentVersion":"17.0.15855.0","Component
version":"17.0.15855.0","eventId":"RT0020","endpoint":"BC170/ODataV4/Company()/purchaseDocumentLines","deprecatedKeys":"Company
name, AL Object Id, AL Object type, AL Object name, AL Stack trace, Client type, Extension name, Extension App Id, Extension
version, Telemetry schema version, Component, Component version, Telemetry schema version, AadTenantId, Environment name,
Environment type","aadTenantId":"common","Environment type":"Production","authenticationStatus":"Succeeded"}

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Analyzing Incoming Web Services Request
Telemetry
2/6/2023 • 5 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1

Web services telemetry gathers data about SOAP, OData, and API requests through the service. It provides
information like the request's endpoint, time to complete, the SQL statements run, and more.

General dimensions
The following table explains the general dimensions included in an incoming Web Ser vices Call trace. The
table lists the dimensions that are specific to Business Central.

DIM EN SIO N DESC RIP T IO N O R VA L UE

operation_Name Web Ser vices Call

Note: The use of the operation_Name column was


deprecated in version 16.1. In future versions, data won't be
stored in this column. So in version 16.1 and later, use the
custom dimension column eventID column custom in
Kusto queries instead of operation_Name .

message Version 16.1 and later (depending on the type):


Web ser vice called (API): {endpoint}
Web ser vice called (ODataV4): {endpoint}
Web ser vice called (ODataV3): {endpoint}
Web ser vice called (SOAP): {endpoint}
Before version 16.1:
Received a web ser vice request of type API
Received a web ser vice request of type
ODataV4
Received a web ser vice request of type
ODataV3
Received a web ser vice request of type SOAP

severityLevel 1

Custom dimensions
The following table explains the custom dimensions included in a Web Ser vices Call trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .
DIM EN SIO N DESC RIP T IO N O R VA L UE

alObjectId Specifies the ID of the AL object that was run by request.[1]

alObjectName Specifies the name of the AL object that was run by the
request.[1]

alObjectType Specifies the type of the AL object that was run by the
request.[1]

category Specifies the service type. Values include: API , ODataV4 ,


ODataV3 , and SOAP .

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

endpoint Specifies the endpoint for the request.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId RT0008

This dimension was introduced in Business Central 2020


release wave 1, version 16.1.

httpHeaders Introduced in version 16.3. Specifies the http headers set in


the request. In version 17.3, a truncated version of the
Authorization header was introduced to enable querying for
the use of basic or token authorization.

httpMethod Introduced in version 16.3. Specifies the HTTP method used


in the request. Values include: POST, GET, PUT, PATCH,
orDELETE.
DIM EN SIO N DESC RIP T IO N O R VA L UE

httpStatusCode Introduced in version 16.3. Specifies the http status code


returned when a request has completed. This dimension
further indicates whether request succeeded or not, and
why. Use it to verify whether there was an issue with a
request even though the request was logged as successful.
The dimension displays one of the following values:
200
OK. The request succeeded.
401
Access denied. The user who made the request
doesn't have proper permissions. For more
information, see Web Services Authentication and
Assign Permissions to Users and Groups.
404
Not found. The given endpoint wasn't valid. For more
information, see Publishing a Web Service
408
Request timed out. The request took longer to
complete than the threshold configured for the
service. For information about this threshold in
Business Central online, see OData request limits. For
on-premises, the timeout is determined by the
ODataServicesOperationTimeout setting of the
Business Central Server. For more information, see
Configuring Business Central Server
429
Too Many Requests. The request exceeded the
maximum simultaneous requests allowed on the
service. For information about this threshold in
Business Central online, see OData request limits. For
on-premises, the timeout is determined by the
ODataMaxConnections setting of the Business
Central Server. For more information, see Configuring
Business Central Server

Data isn't populated for SOAP endpoints.

serverExecutionTime Specifies the amount of time it took the server to complete


the request**. The time has the format hh:mm:ss.sssssss.
Time spent in the request queue isn't included.

sqlExecutes Specifies the number of SQL statements that the request


executed.[1] [2]

sqlRowsRead Specifies the number of table rows that were read by the
SQL statements.[1] [2]

totalTime Specifies the amount of time it took to process the


request.[2]

The time has the format hh:mm:ss.sssssss. Time spent in the


request queue isn't included.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

1
1

This dimension isn't relevant for $metadata calls, like https://localhost:7048/BC/ODataV4/$metadata , so it won't
be in the trace.
2

From telemetrySchemaVersion 0.6 and onwards, this value also includes the CompanyOpen operation.

Analyze web service call performance using telemetry


As a developer, you use the data to learn about conditions that you can change to improve performance. The
following table provides some examples:

C O N DIT IO N A N A LY SIS

A web service request results in a long running SQL query Adjust or fine-tune code.

Web service requests to a specific endpoint read more rows Consider adding filtering to limit the rows that are read.
than requests to the other endpoints

Fewer API type requests compared with other types With SOAP and OData requests to UI pages, computation
resources are used on UI elements that aren't relevant.
Instead of exposing normal pages as web service endpoints,
use the built-in API pages. API pages are optimized for this
scenario.

High number of requests to endpoints that include Power BI This condition may indicate excessive Power BI integration.

For more performance guidelines, see Writing efficient Web Services.

Analyze web service call stability using telemetry


The custom dimension httpStatusCode is key to understanding unsuccessful web service calls. Any call with an
HTTP status code in the 4xx range should be investigated because these calls are likely failing due to a
misconfiguration on the web service client (the caller).
Business Central online and on-premises are configured with various limits on web service requests. For
example, there's a request timeout and a maximum connections limit. For online, you can't change these limits,
but it's helpful to know what the limits are. See Current API Limits. For on-premises, you change the limits on
the Business Central Server instance. See Configuring Business Central Server. Web service calls that exceed the
timeout limit result in a 408 - Request Timeout . These calls are recorded in Application Insights with a
totalTime that is equal to the timeout threshold.

Sample KQL code


To make it easier to get started using Azure Application Insights with Business Central, samples of KQL code are
available in the Business Central BCTech repository on GitHub.
Specifically, the KQL query WebServiceCalls.kql illustrates how to extract HTTP headers, user agents, and
authorization type from web service call telemetry.
If you want to analyze web service call telemetry from the usage of the Microsoft connector (Power BI, Power
Apps, ...), then the query MicrosoftConnectorUsage.kql might be useful.

See also
Monitoring and Analyzing Telemetry Enable Sending Telemetry to Application Insights
Writing efficient Web Services API Limits
Analyzing Outgoing Web Service Request
Telemetry
2/6/2023 • 4 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

Outgoing web service request telemetry gathers data about outgoing web service requests sent using the AL
HTTPClient module. As a partner, the data gives you insight into the execution time and failures that happen in
external services that your environment and extensions depend on. Use the data to monitor environments for
performance issues caused by external services, and be more proactive in preventing issues from occurring.

General dimensions
The following table explains the general dimensions included in an outgoing Web Ser vices Call (Outgoing)
trace. The table lists the dimensions that are specific to Business Central.

DIM EN SIO N DESC RIP T IO N O R VA L UE

message Web Ser vice Called (Outgoing): {endpoint}

severityLevel 1

Custom dimensions
The following table explains the custom dimensions included in a Web Ser vices Call trace.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alAuthenticationMethod Specifies the user authentication used by the Business


Central service . Values include: Windows, UserName,
NavUserPassword, AccessControlService. For more
information about the authentication types, see
Authentication and Credential Types.

alHttpTimeout Specifies the timeout defined for the request. The timeout is
the time to wait before a request gets canceled. The value
has the format hh:mm:ss.

The timeout is defined either by the


NavHttpClientMaxTimeout setting on the Business Central
Server instance or by a TimeOut method call in extension
code. The TimeOut method call takes precedence.

alObjectId Specifies the ID of the AL object that made the request.

alObjectName Specifies the name of the AL object that made the request.

alObjectType Specifies the type of the AL object that made the request.

companyName Specifies the display name of the Business Central company


from which the request was made.

component Dynamics 365 Business Central Ser ver

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

endpoint Specifies the endpoint for the request. The endpoint is


cleaned to include only the base URI.

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

eventId RT0019

extensionId Specifies the appID of the extension that made the request.

extensionName Specifies the name of the extension that made the request.

extensionVersion Specifies the version of the extension that made the request.
DIM EN SIO N DESC RIP T IO N O R VA L UE

httpHeaders Introduced in version 17.2. Specifies the http headers set in


the request.

httpMethod Specifies the HTTP method used in the outgoing request.


Values include: POST, GET, PUT, PATCH, orDELETE.

httpReturnCode Deprecated in version 17.2. Use the dimension


httpStatusCode instead. Specifies the http status code
returned when a request has completed. This dimension
further indicates whether request succeeded or not, and
why. Use it to verify whether there was an issue with a
request even though the request was logged as successful.
The dimension displays one of the following values:
200
OK. The request succeeded.
404
Not found. The given endpoint wasn't valid.

httpStatusCode Specifies the http status code returned when a request has
completed. This dimension further indicates whether request
succeeded or not, and why. Use it to verify whether there
was an issue with a request even though the request was
logged as successful. The dimension displays one of the
following values:
200
OK. The request succeeded.
404
Not found. The given endpoint wasn't valid.
In the case of a failure, the reason for the underlying issue
could be network connectivity, DNS failure, server certificate
validation or timeout. The Business Central Server does not
know which if these it might be.

serverExecutionTime Specifies the amount of time it took the server to complete


the request, including the time to open the company. The
time has the format hh:mm:ss.sssssss.

totalTime Specifies the amount of time it took to process the request,


including the time to open the company. The time has the
format hh:mm:ss.sssssss.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Example trace
The following code snippet is a CustomDimensions example:
{"Telemetry schema version":"0.2","telemetrySchemaVersion":"0.2","Component version":"17.0.15765.0","Environment type":"Production","componentVersion":"17.0.15765.0","Env
AL Object Id, AL Object type, AL Object name, AL Stack trace, Client type, Extension name, Extension App Id, Extension version, Telemetry schema version, Component, Compo
version":"17.0.15821.0","extensionVersion":"17.0.15821.0","Extension App Id":"11111111-aaaa-2222-bbbb-333333333333","aadTenantId":"afbb64dc-bc88-43a3-9153-dd9d2fde08e6","
type":"CodeUnit","Extension name":"Base Application","AL Object name":"My Codeunit","component":"Dynamics 365 Business Central Server","companyName":"CRONUS USA, Inc.","e
Codeunit","alObjectType":"CodeUnit","extensionId":"11111111-aaaa-2222-bbbb-
333333333333","eventId":"RT0019","httpMethod":"GET","serverExecutionTime":"00:00:00.1971767","totalTime":"00:00:00.1971767","endpoint":"https://mycorp.dynamics.com/api/di

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Telemetry Event IDs in Application Insights
2/6/2023 • 10 minutes to read • Edit Online

The following tables list the Ids of Business Central telemetry trace events that are emitted into Azure
Application Insights.

Application events
EVEN T ID A REA M ESSA GE

AL0000CTV Email Email sent successfully

AL0000CTE Field monitoring Sensitive field value has changed:


{alfieldCaption} ({alFieldNumber}) in
table {altableCaption}
({alTableNumber})

AL0000CTP Email Failed to send email

AL0000DD3 Field monitoring Sensitive field monitor status has


changed to {almonitorStatus}

AL0000EMW Field monitoring Sensitive field added to or removed


from monitor: {alfieldCaption}
({alFieldNumber}) in table
{alTableCaption} ({alTableNumber})

AL0000E2A Permissions User-defined permission set added:


{alPermissionSetId}

AL0000E2B Permissions User-defined permission set removed:


{alPermissionSetId}

AL0000E28 Permissions Permission set link added:


{alSourcePermissionSetId} ->
{alLinkedPermissionSetId}

AL0000E29 Permissions Permission set link removed:


{alSourcePermissionSetId} ->
{alLinkedPermissionSetId}

AL0000E2C Permissions Permission set assigned to user:


{alPermissionSetId}

AL0000E2D Permissions Permission set removed from user:


{alPermissionSetId}

AL0000E2E Permissions Permission set assigned to user group:


{alPermissionSetId}

AL0000E2F Permissions Permission set removed from user


group: {alPermissionSetId}
EVEN T ID A REA M ESSA GE

AL0000D3L Retention Policy Retention Policy Log Entry Logged:


{alMessageType}

AL0000D6H Retention Policy Records Deleted Using Retention


Policy: Deleted {alRecordsDeleted}
records from Table {alTableNo},
{alTableName}

AL0000D6I Retention Policy First retention policy enabled on:


{alCompanyName}

AL0000D6J Retention Policy Last retention policy disabled on:


{alCompanyName}

AL0000I74 Azure Function Integration Request sent to Azure function


succeeded: {Function Host}

AL0000I75 Azure Function Integration Authorization failed to Azure function:


{Function Host}

AL0000I7P Azure Function Integration Request sent to Azure function failed:


{Function Host}

Client events
EVEN T ID A REA M ESSA GE

CL0001 Page views Page opened: {alObjectName}

CL0002 UI quality User gave feedback on error message:


[OK|Not OK]

Lifecycle events
EVEN T ID A REA M ESSA GE

AL0000E24 Job Queue Lifecycle Job queue entry enqueued:


{alJobQueueId}

AL0000E25 Job Queue Lifecycle Job queue entry started:


{alJobQueueId}

AL0000E26 Job Queue Lifecycle Job queue entry finished:


{alJobQueueId}

AL0000E3F Configuration Package Configuration package export started:


{alPackageCode}

AL0000E3G Configuration Package Configuration package exported


successfully: {alPackageCode}
EVEN T ID A REA M ESSA GE

AL0000E3H Configuration Package Configuration package import started:


{alPackageCode}

AL0000E3I Configuration Package Configuration package imported


successfully: {alPackageCode}

AL0000E3N Configuration Package Configuration package apply started:


{alPackageCode}

AL0000E3O Configuration Package Configuration package applied


successfully: {alPackageCode}

AL0000E3P Configuration Package Configuration package deleted


successfully: {alPackageCode}

AL0000EJ9 Extension Lifecycle Upgrade tag searched for:


{AlUpgradeTag}

AL0000EJA Extension Lifecycle Upgrade tag set: {AlUpgradeTag}

AL0000EIQ User Checklist Lifecycle User checklist status updated:


{oldStatus} to {newStatus}

LC0001 Company Lifecycle Company created: {companyName}

LC0002 Company Lifecycle Company creation canceled:


{companyName}

LC0003 Company Lifecycle Company creation failed:


{companyName}

LC0004 Company Lifecycle Company copied:


{companyNameSource} to
{companyNameDestination}

LC0005 Company Lifecycle Company copied canceled:


{companyNameSource} to
{companyNameDestination}

LC0006 Company Lifecycle Company copy failed:


{companyNameSource} to
{companyNameDestination}

LC0007 Company Lifecycle Company deleted: {companyName}

LC0008 Company Lifecycle Company deletion canceled:


{companyName}

LC0009 Company Lifecycle Company deletion failed:


{companyName}
EVEN T ID A REA M ESSA GE

LC0010 Extension Lifecycle Extension installed successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0011 Extension Lifecycle Extension failed to install:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0012 Extension Lifecycle Extension synchronized successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId}

LC0013 Extension Lifecycle Extension failed to synchronize:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0014 Extension Lifecycle Extension published successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0015 Extension Lifecycle Extension failed to publish:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0016 Extension Lifecycle Extension un-installed successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0017 Extension Lifecycle Extension failed to un-install:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0018 Extension Lifecycle Extension unpublished successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0019 Extension Lifecycle Extension failed to un-publish:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0020 Extension Lifecycle Extension compiled successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})
EVEN T ID A REA M ESSA GE

LC0021 Extension Lifecycle Extension failed to compile:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0022 Extension Lifecycle Extension updated successfully:


{extensionName} version
{extensionVersion} by
{extensionPublisher}

LC0023 Extension Lifecycle Extension failed to update:


{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0024 Table Index Lifecycle Index enabled: {tableName}

LC0025 Table Index Lifecycle Index disabled: {tableName}

LC0026 Extension Lifecycle Dependent Extension installed


successfully: {extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0027 Extension Lifecycle Dependent extension un-installed


successfully: {extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0028 AppSource Submission AppSource submission validation


request started: {validationRequestId}

LC0029 AppSource Submission AppSource submission validation


request completed successfully:
{validationRequestId}

LC0030 AppSource Submission (Version, country-region) validation


started: version {version},
country/region {countryRegion}

LC0031 AppSource Submission (Version, country-region) validation


completed successfully: version
{version}, country/region
{countryRegion}

LC0032 AppSource Submission Extension validation started: version


{version}, country/region
{countryRegion} for extension
{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})
EVEN T ID A REA M ESSA GE

LC0033 AppSource Submission Extension validation completed


successfully: version {version},
country/region {countryRegion} for
extension {extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0034 AppSource Submission Validation diagnostic reported: version


{version}, country/region
{countryRegion} for extension
{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0035 AppSource Submission AppSource submission validation


request completed with failures:
{validationRequestId}

LC0036 AppSource Submission (Version, country-region) validation


completed with failures: version
{version}, country-region
{countryRegion}

LC0037 AppSource Submission Extension validation completed with


failures: version {version}, country-
region {countryRegion} for extension
{extensionName} version
{extensionVersion} by
{extensionPublisher} ({extensionId})

LC0038 AppSource Submission Diagnostic reported on AppSource


submission validation request:
{validationRequestId}

LC0040 Task Scheduler Task {taskId} created:


{codeunitObjectId} scheduled to run
after {notBefore}. Ready to run:
{isReady}

LC0041 Task Scheduler Task {taskId} ready: {codeunitObjectId}


set ready to run after {notBefore}.

LC0042 Task Scheduler Task {taskId} removed:


{codeunitObjectId}.

LC0043 Task Scheduler Task {taskId} main/failure codeunit


{codeunitObjectId} completed.

LC0044 Task Scheduler Task {taskId} main/failure codeunit


{codeunitObjectId} canceled.

LC0045 Task Scheduler Task {taskId} main/failure codeunit


{codeunitObjectId} failed.

LC0046 Profile Configuration Lifecycle Profile import succeeded: {ProfileId} in


app/extension {ProfileAppId}
EVEN T ID A REA M ESSA GE

LC0047 Profile Configuration Lifecycle Profile import failed: {ProfileId} in


app/extension {ProfileAppId}

LC0048 Profile Configuration Lifecycle Profiles exported successfully

LC0049 Profile Configuration Lifecycle Profiles failed to be exported

LC0050 Profile Configuration Lifecycle Profile copy succeeded: {ProfileId} to


{NewProfileId} from app/extension
{ProfileAppId} to app/extension
{NewProfileAppId}

LC0051 Profile Configuration Lifecycle Profile copy failed: {ProfileId} to


{NewProfileId} from app/extension
{ProfileAppId} to app/extension
{NewProfileAppId}

LC0052 Profile Configuration Lifecycle Profile created successfully: {ProfileId}


in app/extension {ProfileAppId}

LC0053 Profile Configuration Lifecycle Profile removed: {ProfileId} in


app/extension {ProfileAppId}

LC0054 Profile Configuration Lifecycle Profile page customization removed:


{ProfileId} in app/extension
{ProfileAppId}

LC0055 Profile Configuration Lifecycle Profile page customization converted:


{ProfileId} in app/extension
{ProfileAppId}

LC0056 Extension Lifecycle Extension is already synchronized:


{extensionName}

LC0100 Environment Environment update available for


scheduling: {environmentName} to
version {destinationVersion}.

LC0101 Environment Environment update scheduled:


{environmentName} to version
{destinationVersion}, update on or
after date:
{registeredForUpdateOnOrAfterDateUt
c}

LC0102 Environment Environment update missed:


{environmentName} to version
{destinationVersion}

LC0103 Environment Environment update postponed:


{environmentName} to version
{destinationVersion}
EVEN T ID A REA M ESSA GE

LC0104 Environment Environment update resumed:


{environmentName} to version
{destinationVersion}

LC0105 Environment Environment update started:


{environmentName} to version
{destinationVersion}

LC0106 Environment Environment updated successfully:


{environmentName} to version
{destinationVersion}

LC0107 Environment Environment failed to update:


{environmentName} to version
{destinationVersion}

LC0110 Environment Environment restart operation


initiated: {environmentName}

LC0111 Environment Environment restarted successfully:


{environmentName}

LC0112 Environment Environment restart operation failed:


{environmentName}

LC0113 Environment Environment start operation initiated:


{environmentName}

LC0114 Environment Environment started successfully:


{environmentName}

LC0115 Environment Environment start operation failed:


{environmentName}

LC0116 Environment Environment stop operation initiated:


{environmentName}

LC0117 Environment Environment stopped successfully:


{environmentName}

LC0118 Environment Environment stop operation failed:


{environmentName}

LC0119 Environment Environment copy operation started


on source: {environmentName} to
{destinationEnvironmentName}

LC0120 Environment Environment copied successfully:


{environmentName} to
{destinationEnvironmentName}

LC0121 Environment Environment copy operation failed on


source: {environmentName} to
{destinationEnvironmentName}
EVEN T ID A REA M ESSA GE

LC0122 Environment Environment copy operation started


on destination: {environmentName}
from {sourceEnvironmentName}

LC0123 Environment Environment copied successfully to


destination: {environmentName} from
{sourceEnvironmentName}

LC0124 Environment Environment copy operation failed on


destination: {environmentName} from
{sourceEnvironmentName}

LC0125 Environment Environment point-in-time restore


operation started on source:
{environmentName} to
{destinationEnvironmentName}

LC0126 Environment Environment point-in-time restored


successfully: {environmentName} to
{destinationEnvironmentName}

LC0127 Environment Environment point-in-time restore


operation failed on source:
{environmentName} to
{destinationEnvironmentName}

LC0128 Environment Environment point-in-time restore


operation started on destination:
{environmentName} from
{sourceEnvironmentName}

LC0129 Environment Environment point-in-time restored


successfully to destination:
{environmentName} from
{sourceEnvironmentName}

LC0130 Environment Environment point-in-time restore


operation failed on destination:
{environmentName} from
{sourceEnvironmentName}

LC0131 Environment Environment move to


{destinationAadTenantId} AAD tenant
operation scheduled to run at
{registeredForMoveDateUtc}:
{sourceEnvironmentName}

LC0132 Environment Environment move to


{destinationAadTenantId} AAD tenant
operation scheduling failed:
{sourceEnvironmentName}

LC0133 Environment Environment move to


{destinationAadTenantId} AAD tenant
operation started:
{sourceEnvironmentName}
EVEN T ID A REA M ESSA GE

LC0134 Environment Environment moved to


{destinationAadTenantId} AAD tenant
successfully: {sourceEnvironmentName}

LC0135 Environment Environment move to


{destinationAadTenantId} AAD tenant
operation failed:
{sourceEnvironmentName}

LC0136 Environment Environment session {sessionId}


cancellation started:
{environmentName}

LC0137 Environment Environment session {sessionId}


cancelled successfully:
{environmentName}

LC0138 Environment Environment session {sessionId}


cancellation failed: {environmentName}

LC0139 Environment Environment database export


operation started: {environmentName}

LC0140 Environment Environment session {sessionId}


cancelled successfully:
{environmentName}

LC0141 Environment Environment session {sessionId}


cancellation failed: {environmentName}

LC0142 Environment Environment configuration key


{environmentConfigurationKey}
updated for environment
{environmentName} to value:
{newValue}

LC0143 Environment Environment configuration key


{environmentConfigurationKey} failed
to update for environment
{environmentName}

LC0144 Environment Environment configuration key


{environmentConfigurationKey}
deleted for environment
{environmentName}

LC0145 Environment Environment configuration key


{environmentConfigurationKey} failed
to delete for environment
{environmentName}

LC0146 Environment Environment update window was


modified for environment:
{environmentName}
EVEN T ID A REA M ESSA GE

LC0147 Environment Environment update window


modification failed for environment:
{environmentName}

LC0149 Environment Environment delete operation started:


{environmentName}

LC0150 Environment Environment deleted successfully:


{environmentName}

LC0151 Environment Environment delete operation failed:


{environmentName}

LC0152 Environment Environment rename operation


started: {environmentName}

LC0153 Environment Environment renamed successfully:


{environmentName}

LC0154 Environment Environment rename operation failed:


{environmentName}

LC0155 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion}
scheduled for environment:
{environmentName}

LC0156 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion}
scheduling failed for environment:
{environmentName}

LC0157 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion} was
cancelled for environment:
{environmentName}

LC0158 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion} started
for environment: {environmentName}

LC0159 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion} applied
successfully for environment:
{environmentName}

LC0160 Environment Environment app '{extensionName}'


hotfix to version
{extensionDestinationVersion} failed for
environment: {environmentName}
EVEN T ID A REA M ESSA GE

LC0161 Extension Lifecycle Environment app {extensionName}


install to version
{extensionDestinationVersion}
scheduled for environment:
{environmentName}

LC0162 Extension Lifecycle Environment app {extensionId}, version


{extensionDestinationVersion}
installation scheduling failed for
environment: {environmentName}

LC0163 Extension Lifecycle Environment app {extensionId}, version


{extensionDestinationVersion}
installation started for environment:
{environmentName}

LC0164 Extension Lifecycle Environment app {extensionName},


version {extensionVersion} installation
succeeded for environment:
{environmentName}

LC0165 Extension Lifecycle Environment app {extensionName},


version {extensionDestinationVersion}
installation failed for environment:
{environmentName}

LC0166 Extension Lifecycle Environment app {extensionName},


version {extensionDestinationVersion}
installation/update requires
automatically installing a new
dependency app
dependencyExtensionName}, version
{dependencyExtensionDestinationVersi
on} for environment:
{environmentName}

LC0167 Extension Lifecycle Environment app {extensionName}


update to version
{extensionDestinationVersion}
scheduled for environment:
{environmentName}

LC0168 Extension Lifecycle Environment app {extensionId} update


to version
{extensionDestinationVersion}
scheduling failed for environment:
{environmentName}

LC0169 Extension Lifecycle Environment app {extensionId} update


to version
{extensionDestinationVersion} started
for environment: {environmentName}
EVEN T ID A REA M ESSA GE

LC0170 Extension Lifecycle Environment app {extensionId} update


to version
{extensionDestinationVersion}
succeeded for environment:
{environmentName}

LC0171 Extension Lifecycle Environment app {extensionId} update


to version
{extensionDestinationVersion} failed for
environment: {environmentName}

LC0173 Extension Lifecycle Environment app {extensionName}


uninstall scheduled for environment:
{environmentName}

LC0174 Extension Lifecycle Environment app {extensionId}


uninstall scheduling failed for
environment: {environmentName}

LC0175 Environment Environment data upgrade operation


started: {environmentName}

LC0176 Environment Environment data upgrade operation


completed successfully:
{environmentName}

LC0177 Environment Environment data upgrade operation


failed: {environmentName}

LC0178 Environment Recovery from a failed data upgrade


operation has completed successfully:
{environmentName}

LC0179 Environment Recovery from a failed data upgrade


operation has failed:
{environmentName}

Runtime events
EVEN T ID A REA M ESSA GE

RT0001 Authorization AuthorizationFailed(PreOpenCompany)


: {failure reason}

RT0002 Authorization Authorization Failed (Open Company):


{failure reason}

RT0003 Authorization AuthorizationSucceeded(PreOpenCom


pany)

RT0004 Authorization Authorization Succeeded (Open


Company)
EVEN T ID A REA M ESSA GE

RT0005 Performance Operation exceeded time threshold


(SQL query)

RT0006 Report generation Success report generation

RT0006 Report generation Report rendering failed: {report ID} -


{report name}

RT0007 Report generation Cancellation report generation

RT0008 Incoming Web service requests Web service called ({category of


request}): {endpoint}

RT0010 Extension lifecycle Extension Update Failed: exception


raised in extension {extensionName} by
{extensionPublisher} (updating to
version {extensionTargetedVersion})

RT0011 Report generation Report cancelled but a commit


occurred

RT0012 Performance Database lock timed out

RT0013 Performance Database lock snapshot: {snapshotId}

RT0014 Security App Key Vault initialization succeeded:


'{keyVaultUri}'

RT0015 Security App Key Vault initialization failed

RT0016 Security App Key Vault secret retrieval


succeeded from key vault
'{keyVaultUri}'

RT0017 Security App Key Vault secret retrieval failed


from key vault: '{keyVaultUri}'

RT0018 Performance Operation exceeded time threshold (AL


method)

RT0019 Outgoing Web service requests Web Service Called (Outgoing):


{endpoint}

RT0020 Web service key request Authentication with Web Service Key
succeeded: {endpoint}

RT0021 Web service key request Authentication with Web Service Key
failed: {endpoint}

RT0023 Troubleshooting Verbose telemetry enabled for session:


{sessionId}
EVEN T ID A REA M ESSA GE

RT0024 Troubleshooting Verbose telemetry disabled for session:


{sessionId}

RT0025 Performance Database wait statistics snapshot


taken: {snapshotId}

RT0026 Performance Database wait statistics snapshot


entry: {databaseWaitStatisticsCategory}

RT0028 Performance Database deadlock occurred

RT0029 Sessions The StopSession method was invoked


on session {failureReason}

RT0030 Error method call Error dialog displayed: {errorMessage}

RT0031 Permission error Permission error shown

RT0032 Permission error Dependency cycle discovered in


permission sets

See also
Monitoring and Analyzing Telemetry
Enable Sending Telemetry to Application Insights
Managing Technical Support
2/6/2023 • 14 minutes to read • Edit Online

When users report a problem with Business Central, superusers or the internal administrator can often find a
solution. The internal administrator can find technical information in the Help and Suppor t page, and they can
then escalate relevant issues to the reselling partner.
The reselling partner can sign in to their customer's Business Central as the delegated admin for
troubleshooting. Sometimes, they create a sandbox environment based on production data or troubleshooting.
Both internal administrators and their partner can use the Business Central administration center to manage
environments, updates, and troubleshooting.

Internal administrators
The internal administrator can work with users to identify solutions or workarounds, such as missing setup,
missing permissions, and other issues. If users aren't sure if things aren't working as intended, they can check
the Help and Learn content for the intended behavior. For more technical problems, administrators can find
information in the Help and Suppor t page to help with this investigation. For more information, see the
Finding technical information section.
As the tenant admin, you can check the Microsoft 365 admin center for incidents. For more information, see the
Monitor service health section.
Internal administrators can also create sandbox environments for deeper troubleshooting, for example, before
they decide to contact their partner for technical support. The partner must have specified their support contact
details in the Help and Suppor t page.

Delegated administrators
Each Business Central customer has a partner who assists with technical support when requested by the internal
administrator. As the partner, you must have specified support contact details in the Help and Suppor t page.
For more information, see Configuring the support experience.

IMPORTANT
You must have set up users in your own tenant in Partner Center as either Admin agent or Helpdesk agent, and they
must have delegated administration privileges in your customer's Business Central to support the customer. For more
information, see Delegated Administrator Access to Business Central Online.

The delegated administrator can access the customer's Business Central for further troubleshooting. They can
also use the Business Central administration center to analyze telemetry, create a sandbox environment for
debugging or step-by-step reproduction, for example.
If the partner can't find a solution, they can request support from Microsoft. For more information, see the
Escalating support issues to Microsoft section.
Extend trials
Another task for a delegated admin is to help with extending trials. For more information, see Business Central
Trials and Subscriptions.
Cleaning up settings
If you end the relationship with a customer, you must remove certain settings while you still have access to that
customer's Business Central administration center. Consider the following settings:
Support contact details
For more information, see To supply your support contact information in the administration center.
Notification recipients
For more information, see Tenant Notifications.
Application Insights key (if the partner had set up Application Insights)
For more information, see Environment Telemetry in the Business Central administration center.

Finding technical information


For Business Central online, administrators have access to a range of tools for troubleshooting. Depending on
the type of problem, administrators can troubleshoot in Business Central, or they can use the Business Central
administration center to analyze telemetry, for example.
This section provides an overview of the most useful tools for troubleshooting the problems that users are
reporting. Often, you'll want to create a sandbox environment based on the production environment where
users are reporting problems. That way, the administrators can troubleshoot without disturbing normal work.
The Help and Suppor t page
Each company in any Business Central environment has a Help and Suppor t page that can be accessed
from the question mark in the top-right corner. Here you can access the latest error message, which, for
example, is useful if your users complain of a confusing error message such as Sorry, we just updated
this page. Please close and reopen.. For more information, see The Help and Support page section.
Page inspection
Business Central includes a page inspection feature that lets you get details about a page. You can get
insight into the page design, the different elements that form the page, and the source behind the data
that it shows. For more information, see Inspecting and Troubleshooting Pages.
Environment telemetry in the Business Central administration center
In the Business Central administration center, you can view telemetry of top-level AL events, and any
errors resulting from calls through the telemetry stack. For more information, see Environment
telemetry.
Troubleshoot in a sandbox environment
In the Business Central administration center, you can create sandbox environments for safe debugging
and troubleshooting. For more information, see Sandbox environments.
Use the Event Recorder
Using the Event Recorder, you can record the events that are published and raised while performing the
actions of your scenario. For more information, see Discoverability of Events.
Check the data in the database
You can view table objects in Business Central. This way, you see the data in all rows and columns of a
specific table, including any columns that are added by table extensions. From the Business Central
administration center, you can also launch a list of all tables, sorted by storage size. For more information,
see Viewing Table Data.
Analyze long running operations in Application Insights
Set up Application Insights so that any SQL query that takes longer than 1000 milliseconds to execute
will be sent to your Application Insights resource. For more information, see Analyzing long-running
operations in Application Insights.
Database locks
Open the Database Locks page in Business Central to view existing locks in this tenant's database. You
can often see which where the code is tht caused the problem.
Additional logging per session
You can enable more logging that can help you troubleshoot in the current session. For example, if you're
concerned if a specific report or other process might be the reason for database locks, go to the Help
and Suppor t page and enable more logging. Then, run the process that you're concerned about, and
then analyze the logs. For more information, see Analyzing long running operations in Application
Insights.
Debug your app or pre-tenant extension
With Visual Studio Code and the AL Language extension, you get an integrated debugger to help you
inspect your code to verify that your application can run as expected. For more information, see
Debugging in AL.
Correct customer data in bulk
The Business Central add-in for Excel is the preferred tool for bulk correcting customer data in case of
data-related issues. For more information, see Get the Business Central Add-in for Excel and Viewing and
Editing in Excel from Business Central.
The Help and Support page in the Business Central company
The Help and Suppor t page is a powerful tool for administrators to find technical information about Business
Central, both online and on-premises. The Troubleshooting section gives easy access to the most recent error
message, and it has a link to inspect pages for further troubleshooting.

Also in the Help and Suppor t page, users can see support contact information, if the partner has provided this
information. For more information, see To supply your support contact information in the administration center.
The Help and Suppor t page also shows which version of Business Central, the specific environment is on.
For Business Central online, a user can enable more logging and then perform the operation that is causing
problems. The more telemetry is sent to Application Insights where you can do further troubleshooting, either
as part of a support case, or before you submit a support request. In both scenarios, the more details about the
problematic operation will lead to a quicker resolution.
For Business Central online, internal and delegated administrators also have access to this information in the
Business Central administration center. You can use the Business Central administration center to easily navigate
to the different environments in a tenant, and you can create sandbox environments that can help troubleshoot
any issues reported by users. For more information, see The Business Central Administration Center.
Azure Active Directory tenant
When the internal administrator wants to contact the partner for support, then the Help and Suppor t page
encourages them to include information about their Azure Active Directory tenant ID in the email. This
information is shown in the Troubleshooting section at the bottom of the Help and Suppor t page.
The delegated administrator can use that to identify the tenant in the Partner Center and in the Business Central
administration center for troubleshooting.
Version
You can use the information about which version the tenant is on to help you troubleshoot the issue that the
customer has reported, for example. This information is also listed in the Troubleshooting section of the Help
and Suppor t page. For more information, see Version numbers in Business Central.
Last known error
The link behind the sentence View the last known error will find and show the most recent error message that
was generated by the application code. This includes errors from field validation, posting routines, and other
code behind business functionality.
The information that you can get from this link includes the following:
Text
This is the error message that the user sees, either in a dialog window or next to a user interface element
that can't render, for example.
Code
This is the code snippet that threw the error.
Callstack
This shows how the error was triggered.
Object
This shows information about the runtime objects.
The link can't open errors that were generated by the platform. If you suspect that the issue is caused by the
platform, try to reproduce the error in a sandbox environment before you contact Microsoft for support. For
more information, see Create a new environment.

TIP
If your users complain of a confusing error message such as Sorry, we just updated this page. Please close and reopen.,
then you can often find the underlying problem either in this last known error, or by analyzing telemetry in the Business
Central administration center. For example, in the case of the Sorry, we just updated this page. Please close and reopen.
message, the underlying problem is often that two users are trying to modify the same data. So if both users open the
same sales order, and both change a field, then one of them will see the Sorry, we just updated this page. Please close and
reopen. message, because Business Central saves changes as soon as you move to the next field or close the page.

Monitor service health


Both as an internal admin and as a delegated admin, you can help users determine the cause of their problems
in different ways before you have to escalate the issue to Microsoft Support. The starting point is the Business
Central administration center where you can access telemetry for the tenant and check the status of already
reported outages. For more information, see Managing Production and Sandbox Environments in the Admin
Center.
The Microsoft 365 admin center provides an overview of service health across Microsoft services. Select
Preferences to receive service health email notifications about incidents across Business Central, Microsoft
365, and other Microsoft services. For more information, see How to check service health. If you manage more
than one tenant, see View service health for all accounts.
As a partner, use the Partner Center to get an overview of service health for each customer. For more
information, see Check service health for a customer in the Partner Center content. You can also use APIs for
automated service notifications for Azure Insights & Office 365 service communications.

Escalating support issues to Microsoft


Sometimes the tenant has run into a problem that the partner can't resolve. In those cases, the delegated admin
can use the Partner Center or the Business Central administration center to submit a support request to
Microsoft.
Both internal and delegated administrators can access Business Central administration center, and then, in the
Suppor t menu, choose the New Suppor t Request button. This link signs you in to the Power Platform Admin
Center. Here, you can launch the New Suppor t Request guide that will help you identify potential solutions or
workarounds based on how you fill in the various fields.

TIP
In the Power Platform Admin Center, use the See solutions button to find potential guidance or workarounds. Based on
your search keywords, links to suggested content are shown on the Solutions tab.

NOTE
The internal administrator cannot contact Microsoft directly. If you are an internal admin and suspect that something is
wrong with your Business Central, you must contact your partner for next steps.

Submitting support requests on behalf of your customer


Your company must be registered as a Microsoft partner, and it must have the Advanced Support for Partners
(ASfP) or Premier support plan. Your service account manager can get you more information about getting the
ASfP. If you already have a support plan, the Technical Benefits tab in the Partner Center lists the contract ID and
access ID that you must specify when you submit a new support request on behalf of your customer. If you're
not sure how to find the information, the service account manager can get the information for you.
As the delegated administrator, if you are logged into the Business Central administration center, you can use the
New Suppor t Request link in the Suppor t menu to submit a support request on behalf of your customer.

TIP
Alternatively, you can use customer-specific URLs such as
https://admin.powerplatform.microsoft.com/account/login/[customer tenant ID] .

Your company must be registered as a Microsoft partner, and it must have the Advanced Support for Partners
(ASfP) or Premier support plan. Your service account manager can get you more information about getting the
ASfP. If you already have a support plan, the Technical Benefits tab in the Partner Center lists the contract ID and
access ID that you must specify when you submit a new support request on behalf of your customer. If you're
not sure how to find the information, the service account manager can get the information for you.

NOTE
Outages are frustrating but rare. If your customer reports that they cannot access Business Central at all, help them test
their connection and other potential local problems. For more information, see the Report Customer Outages section
here, and also bookmark the article How do I check my online service health? in the Power Platform administration
content.

To start the process of submitting a new support request from the Business Central administration center
1. On the Environments tab of the Business Central administration center, choose the relevant
environment to open the environment details.
2. In the Suppor t menu, choose New Suppor t Request .
A new browser tab opens so that you can submit the support request in the Power Platform Admin
Center.
You are automatically logged in with information about your customer's tenant. Create a new support
request and fill in the fields as appropriate.

TIP
Use the See solutions button to find potential guidance or workarounds. Based on your search keywords, links
to suggested content are shown on the Solutions tab.

You can find most of the necessary information in the Business Central administration center, including the
tenant ID and the Business Central version numbers. For more information, see View solutions or enter a
support request through the new support center in the Power Platform administration content.

IMPORTANT
Your company must be registered as a Microsoft partner, and it must have the Advanced Support for Partners (ASfP) or
Premier support plan. Your service account manager can get you more information about getting the ASfP. If you already
have a support plan, the Technical Benefits tab in the Partner Center lists the contract ID and access ID that you must
specify when you submit a new support request on behalf of your customer. If you're not sure how to find the
information, the service account manager can get the information for you.

The support person can be a member of the Helpdesk agent group in the customer's Azure AD tenant or a
global administrator. For more information, see Delegated Admin Access to Business Central Online.
Microsoft Support will keep you updated on the status of your support request. You can also see the status in
the Power Platform Admin Center. For more information, see Power Platform Admin Center.
To start the process of submitting a new support request from the Partner Center
You can also start the process from the Partner Center. Choose the customer you want to open a case on, and
then follow the support request work flow. You're automatically redirected to the Power Platform admin center
in the context of the customer's tenant.
However, you might need information from the Business Central administration center, which is why we
recommend that route. For more information, see Report problems on behalf of a customer in the Partner
Center content.
See also
How to check service health
Inspecting and Troubleshooting Pages
The Business Central Administration Center
Technical Support for Business Central
Provide technical support (Microsoft Partner Center)
Escalate Support Issues to Microsoft
Deployment Overview
Administration as a partner
Administration of Business Central Online
Administration of Business Central On-Premises
Escalate Support Issues to Microsoft
2/6/2023 • 3 minutes to read • Edit Online

It might happen that a Business Central online customer runs into a technical problem that the partner cannot
resolve. In those cases, the delegated admin can use the Partner Center or the Business Central administration
center to submit a support request to Microsoft.

NOTE
The internal administrator cannot contact Microsoft directly. If you are an internal admin and suspect that something is
wrong with your Business Central online, you can use the Business Central administration center to troubleshoot. To go
further than that, you must contact your partner for next steps.

Submit support requests on behalf of your customer


Your company must be registered as a Microsoft partner, and it must have the Advanced Support for Partners
(ASfP) or Premier support plan. Your service account manager can get you more information about getting the
ASfP. If you already have a support plan, the Technical Benefits tab in the Partner Center lists the contract ID and
access ID that you must specify when you submit a new support request on behalf of your customer. If you're
not sure how to find the information, the service account manager can get the information for you.
As the delegated administrator, if you are logged into the Business Central administration center, you can use the
New Suppor t Request link in the Suppor t menu to submit a support request on behalf of your customer.

TIP
Alternatively, you can use customer-specific URLs such as
https://admin.powerplatform.microsoft.com/account/login/[customer tenant ID] .

Your company must be registered as a Microsoft partner, and it must have the Advanced Support for Partners
(ASfP) or Premier support plan. Your service account manager can get you more information about getting the
ASfP. If you already have a support plan, the Technical Benefits tab in the Partner Center lists the contract ID and
access ID that you must specify when you submit a new support request on behalf of your customer. If you're
not sure how to find the information, the service account manager can get the information for you.

Submit a new support request from the Business Central


administration center
1. On the Environments tab of the Business Central administration center, choose the relevant
environment to open the environment details.
2. In the Suppor t menu, choose New Suppor t Request .
A new browser tab opens so that you can submit the support request in the Power Platform Admin
Center.
You are automatically logged in with information about your customer's tenant. Create a new support
request and fill in the fields as appropriate.
TIP
Use the See solutions button to find potential guidance or workarounds. Based on your search keywords, links
to suggested content are shown on the Solutions tab.

You can find most of the necessary information in the Business Central administration center, including the
tenant ID and the Business Central version numbers. For more information, see View solutions or enter a
support request through the new support center in the Power Platform administration content.

IMPORTANT
Your company must be registered as a Microsoft partner, and it must have the Advanced Support for Partners (ASfP) or
Premier support plan. Your service account manager can get you more information about getting the ASfP. If you already
have a support plan, the Technical Benefits tab in the Partner Center lists the contract ID and access ID that you must
specify when you submit a new support request on behalf of your customer. If you're not sure how to find the
information, the service account manager can get the information for you.

The support person can be a member of the Helpdesk agent group in the customer's Azure AD tenant or a
global administrator. For more information, see Delegated Admin Access to Business Central Online.
Microsoft Support will keep you updated on the status of your support request. You can also see the status in
the Power Platform Admin Center. For more information, see Power Platform Admin Center.

Submit a new support request from the Partner Center


You can also start the process from the Partner Center. Choose the customer you want to open a case on, and
then follow the support request work flow. You're automatically redirected to the Power Platform admin center
in the context of the customer's tenant.
However, you might need information from the Business Central administration center, which is why we
recommend that route. For more information, see Report problems on behalf of a customer in the Partner
Center content.

See Also
Report Customer Outages
Managing Technical Support
Inspecting and Troubleshooting Pages
The Business Central Administration Center
Technical Support for Business Central
Provide technical support (Microsoft Partner Center)
Deployment Overview
Administration as a partner
Administration of Business Central Online
Administration of Business Central On-Premises
Report Customer Outages
2/6/2023 • 2 minutes to read • Edit Online

When a customer has a situation where no users can sign in to Business Central, the admin must take
immediate action. Outages are frustrating but rare. Make sure that the users are not unable to sign in due to
problems with their network connection, for example. For more information, see How do I check my online
service health? in the Power Platform administration content.
Internal and delegated administrators can report this outage to Microsoft by using the Repor t Production
Outage action for the relevant production environment in the Business Central administration center. This
action creates a support ticket for Microsoft with all the information that is needed to begin steps to resolve the
issue.

NOTE
This option is not available in sandbox environments.

To report an outage
1. On the Environments tab of the Business Central administration center, choose the relevant
environment to open the environment details.
2. In the action ribbon, choose Suppor t , and then choose Repor t Production Outage .
3. In the Repor t Production Outage pane, choose the outage type:
Unable to sign in (all users)
Cannot access API/Web Service
4. Enter your name, email address, and phone number. This information will be included in the support
ticket.
5. Choose Next .
6. In the next pane, provide details about the outage, including which browsers users have tried to sign in
with, any companies that you can sign into, and errors and correlation IDs. This information will be
included in the support ticket.
7. Finally, add the date and time when the outage began. This information will also flow to the support
ticket.
8. Choose the consent checkbox, and then choose Repor t .
A support request ticket is then created, and you will see a dialog box with the ticket ID. You can then monitor
progress in the Repor ted Outages section. From there, you can access the tickets in the Partner Center. For
more information, see the Microsoft Partner Center documentation.

See Also
Escalating Support Issues to Microsoft
Managing Technical Support
Inspecting and Troubleshooting Pages
The Business Central Administration Center
Technical Support for Business Central
Provide technical support (Microsoft Partner Center)
Deployment Overview
Administration as a partner
Administration of Business Central Online
Administration of Business Central On-Premises
Performance Profiler Overview
2/6/2023 • 2 minutes to read • Edit Online

If a business process takes longer than expected, your administrator can use the Performance Profiler page to
record a snapshot of the process. While recording, the profiler monitors all of the apps that are involved in the
process. These include first-party apps from Microsoft, such as the Base Application and System Application, and
any third-party apps that you have installed. Identifying where the holdup is can make it easier to go to the
correct support organization or, if you have developers in-house, fix the problem yourself. For more information,
see Viewing technical information.
After you record a snapshot you'll get two types of insights:
The Active Apps chart shows how much faster the process could be if you remove each app.
The Time Spent chart shows how many milliseconds each app took to complete its part. This chart is
available if you turn on the Show technical information toggle.
You can use the App Name and App Publisher actions to filter the charts, for example, to view the
performance of apps from a particular publisher.

TIP
It's a good idea to open the Performance Profiler page in a separate browser window while you record a process. That

makes it easier to return to the profiler to stop the recording. To open the page in a new window, choose the icon in
the upper right of the page.

Viewing technical information


If you want to dig into the technical specifics, you can turn on the Show technical information toggle. That
adds the Time Spent by Application Object and Call Tree FastTabs. The following table describes the
FastTabs.

FA ST TA B DESC RIP T IO N

Time Spent by Application Object This FastTab shows the objects, such as pages, codeunits,
and tables, that were involved in the process. The interesting
things here are the Time Spent and Samples columns. The
Time Spent column focuses on the object, and shows how
long it was active during the recording. The Samples column
shows the number of times that the profiler sampled the
performance of the object.

Call Tree The Self Time and Total Time columns show where time is
spent in the code. The Self Time column shows the amount
of time spent in the method only, and excludes calls out of
the method. The Total Time field is the Self Time amount
plus calls out of the method.

Downloading and Sharing Performance Profiles


If you want to share a recording, for example, if you're in contact with the company that provided an app that
you think is slowing down a process, you can download the recording and then copy the file to OneDrive.

The Performance Profiler and the AL Profiler


The Performance Profiler features are a simplified version of the AL Profiler for the AL Language extension in
Visual Studio Code. You can capture a performance profile of the code that was run during a snapshot. Using the
performance profiling editor view in Visual Studio Code, you can investigate the time spent on a process using
top-down and bottom-up call stack views. For more information, see AL Profiler Overview.

See Also
Managing Technical Support
Escalate support issues to Microsoft
Debugging
Snapshot Debugging
Introduction to automation APIs
2/6/2023 • 5 minutes to read • Edit Online

Automation APIs provide capability for automating company setup through APIs. Once the tenants have been
created, the automation APIs can be used, in order to hydrate the tenant - to bring the tenant up to a desired
state. Usually this involves creating a new company on the tenant, running RapidStart packages, installing
extensions, adding users to user groups and assigning permission sets to users.
Delegated admin credentials and Dynamics 365 Business Central users with permissions, can call the APIs.

IMPORTANT
For delegated admin access, you must add the Azure Active Directory (Azure AD) application to the AdminAgents
group. If the Azure AD application is not added, the consent flow will show an error such as Need pre-consent. For more
information, see Pre-consent your app for all your customers in the Graph documentation.

Automation APIs are placed in the microsoft/automation API namespace. In all the examples below, parameters
are marked in parenthesis {} . Make sure that only valid parameters are passed.

Create a company
To create a company, an automationCompany endpoint is available. To create a Company issue a POST request
as shown in the following example.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/automationCompanies
Authorization: Bearer {token}
Content-type: application/json
{
"name": "CRONUS",
"displayName": "CRONUS",
"businessProfileId": ""
}

The {companyId} must be the ID of an valid company on the tenant. Issue a GET automationCompany request to
fetch existing companies.

NOTE
The company which is created will not be initialized.

To rename a company, issue a PATCH automationCompanies.

Upload and apply a RapidStart package


RapidStart is uploaded, installed, and applied using the APIs described below. RapidStart operations can be time
consuming. To get the current status of the RapidStart packages and running operations issue a GET
configurationPackages as shown in the following example.
GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/configurationPackages

Authorization: Bearer {token}

In the response, status for the import and apply status will be shown, as well as information about the
RapidStart package.
Insert RapidStart
First step is to create the configuration package, by issuing a POST configurationPackages in the Dynamics 365
Business Central tenant. Once the configuration package is created, the RapidStart package can be uploaded.
See the example below.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/configurationPackages

Authorization: Bearer {token}


Content-type: application/json
{
"code":"{SAMPLE}",
"packageName": "{SAMPLE}"
}

Upload RapidStart package


Once the configuration package is created, a RapidStart package can be uploaded with a PATCH
configurationPackages. See the example below.

PATCH https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/configurationPackages({packageId})/file('{SAMPLE}
')/content

Authorization: Bearer {token}


Content-type: application/octet-stream
If-Match: *
Body: RapidStart file.

Import and apply RapidStart package


Once uploaded, the RapidStart package needs to be imported by issuing a POST on the bound action
Microsoft.NAV.import.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/configurationPackages({packageId})/Microsoft.NAV.
import

Authorization: Bearer {token}

When the RapidStart package is imported it can applied with a POST on bound action Microsoft.NAV.apply.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/configurationPackages({packageId})/Microsoft.NAV.
apply

Authorization: Bearer {token}


Managing users, user groups, and permission sets
The automation APIs enable users to be set up in Dynamics 365 Business Central.
Modifying user properties
Get the current user properties by issuing a GET users. This will get the UserSecurityId needed on subsequent
requests.
To modify the user, create a PATCH user request as shown in the example below.

PATCH https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})
Content-type: application/json
If-Match:*
{
"state": "Enabled",
"expiryDate": "2035-01-01T21:03:53.444Z"
}

Assign user permissions and user groups


To assign users to a user group, issue a POST request against the userGroupMembers entity. See the example
below.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userGroupMembers

Authorization: Bearer {token}


{
"code": "D365 EXT. ACCOUNTANT",
"companyName" :"CRONUS USA, Inc."
}

To retrieve the list of user groups issue a GET userGroups. This will return the information that you need for the
payload above.
Assigning permission sets is identical to adding users to user groups. GET permissionSet returns information
about the available permission sets. To assign a permissionSet issue a POST userPermission as shown in the
following example.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userPermissions

Authorization: Bearer {token}


{
"roleId": "SECURITY"
}

Removing the permissionSet from the user is done by issuing a DELETE userPermissions on the users entity.
Get new users from Office 365
To get new users from Office 365, two bound actions on the users endpoint can be used:
Microsoft.NAV.getNewUsersFromOffice365 and Microsoft.NAV.getNewUsersFromOffice365Async . Both actions retrieve
new users or new user information from the Office 365 portal but former one is designed for delegated admins
and it runs synchronous and latter one schedules a background job which makes it asynchronous.
Microsoft.NAV.getNewUsersFromOffice365Async returns a link to the scheduled job where you can track the
progress. You can also track the progress by issuing a GET scheduledJobs on the users entity. Note that existing,
unchanged users will not be updated with these actions.
Handling tenant extensions
Add-on extensions which are already published to the tenant can be installed and uninstalled. Per-tenant
extensions can be uploaded and installed. To get the list of all extensions on the tenant, issue a GET extensions.
This will return the packageId needed for installing and uninstalling extensions.
Installing and uninstalling published add-on extensions
There are three bound actions available on the extensions endpoint: Microsoft.NAV.install ,
Microsoft.NAV.uninstall and Microsoft.NAV.uninstallAndDeleteExtensionData .

Issue a POST extension using the bound actions. See the example below.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/2.0/companies({companyId})/extensions({packageId})/Microsoft.NAV.install

Authorization: Bearer {token}

Upload and install a per-tenant extension


Use extensionUpload endpoint to upload and install the extension.

NOTE
Installing per-tenant extensions using Automation APIs is only possible in SaaS.

Insert extension upload


First step is to create the configuration package, by issuing a POST extensionUpload in the Dynamics 365
Business Central tenant. Once the extension upload record is created, the extension can be uploaded. See the
example below.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/extensionUpload

Authorization: Bearer {token}


Content-type: application/json
{
"schedule":"Current version",
"schemaSyncMode": "Add"
}

NOTE
Schedule in the body can be "Current version", "Next minor version" or "Next major version".

NOTE
Schema Sync Mode in the body can be "Add" or "Force Sync".

Upload extension file


Once the extension upload record is created, an extension file can be uploaded with a PATCH extensionUpload.
See the example below.
PATCH https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/extensionUpload({extensionUploadId})/extensionCon
tent

Authorization: Bearer {token}


Content-type: application/octet-stream
If-Match: *
Body: extension file.

Install extension
Once extension file is uploaded, the extension needs to be installed by issuing a POST on the bound action
Microsoft.NAV.upload.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/extensionUpload({extensionUploadId})/Microsoft.NA
V.upload

Authorization: Bearer {token}

Uninstalling the extension can be done through the bound action Microsoft.NAV.uninstall, as with the add-on
extensions. The bound action Microsoft.NAV.uninstallAndDeleteExtensionData can be used to delete the tables
that contain data owned by the extension on uninstall. This action cannot be undone.
Monitoring extension installation progress
To view ongoing extension installation status, issue GET extensionDeploymentStatus as shown in the following
example.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/extensionDeploymentStatus

See Also
Automation company
Company
Configuration package
Extension
Extension deployment status
Extension upload
Permission set
Profile
Scheduled job
User
User group
User group member
User group permission
User permission
automationCompany resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents an automation company in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET automationCompany automationCompany Gets a automation company object.

DELETE automationCompany none Deletes a automation company object.

POST automationCompany automationCompany Creates a automation company object.

PATCH automationCompany automationCompany Updates a automation company


object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the item. Non-


editable.

name string Represents the automation company's


name.

evaluationCompany boolean Specifies the whether the Company is


an evaluation company.

displayName string Specifies the automation company's


name. This name will appear on all
sales documents for the automation
company.

businessProfileId string Specifies the Business Profile ID linked


to the company.

JSON representation
Here is a JSON representation of the automationCompany resource.
{
"id": "GUID",
"name": "string",
"evaluationCompany": "boolean",
"displayName": "string",
"businessProfileId": "string"
}

See Also
GET automationCompany
DELETE automationCompany
POST automationCompany
PATCH automationCompany
Get automationCompany
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of an automation company object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET /microsoft/automation/v2.0/companies({companyId})/automationCompanies({automationCompanyId})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and an automationCompany object in the
response body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/automationCompanies({automationCompanyId})

Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.
{
"id": "3496bbf8-fcae-4e48-a4f8-cb17c27de0b3",
"name": "CRONUS USA, Inc.",
"evaluationCompany": true,
"displayName": "CRONUS USA, Inc.",
"businessProfileId": ""
}

See Also
Tips for working with the APIs
automationCompany
Delete automationCompany
2/6/2023 • 2 minutes to read • Edit Online

Deletes an automation company from Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

DELETE /microsoft/automation/v2.0/companies({companyId})/automationCompanies({automationCompanyId})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
automationCompany , the automationCompany will
not be updated.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns 204 No Content response code and deletes the automationCompany. It does
not return anything in the response body.

Example
Request
Here is an example of the request.

DELETE https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/automationCompanies({automationCompanyId})

Response
Here is an example of the response.

HTTP/1.1 204 No Content

See Also
Tips for working with the APIs
automationCompany
Create automationCompany
2/6/2023 • 2 minutes to read • Edit Online

Creates an automation company in Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

POST /microsoft/automation/v2.0/companies({companyId})/automationCompanies

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

Request body
In the request body, supply a JSON representation of a automationCompany object.

Response
If successful, this method returns 201 Created response code and a automationCompany object in the
response body.

Example
Request
Here is an example of the request.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/automationCompanies
Content-type: application/json
{
"name": "CRONUS",
"evaluationCompany": false,
"displayName": "CRONUS",
"businessProfileId": ""
}

Response Here is an example of the response.


HTTP/1.1 201 Created
Content-type: application/json
{
"id" : "666631a8-8775-eb11-bb56-000d3a298ab3",
"name" : "CRONUS",
"evaluationCompany" : false,
"displayName" : "CRONUS",
"businessProfileId" : ""
}

See Also
Tips for working with the APIs
automationCompany
Update automationCompany
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of an automation company object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

PATCH /microsoft/automation/v2.0/companies({{companyid}})/automationCompanies({automationCompanyId})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
automationCompany , the automation company will
not be updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 200 OK response code and an updated **automationCompany ** object in
the response body.

Example
Request
Here is an example of the request.

PATCH https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/automationCompanies({automationCompanyId})
Content-type: application/json
If-Match:*
{
"displayName": "My Company",
}
Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.

{
"id": "2b8ea70b-1384-448d-b3d7-1d26c41f3cec",
"name": "CRONUS USA, Inc.",
"evaluationCompany": false,
"displayName": "My Company",
"businessProfileId": ""
}

See Also
Tips for working with the APIs
automationCompany
company resource type (automation)
2/6/2023 • 2 minutes to read • Edit Online

Represents a company in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET company company Gets a company object.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

configurationPackages configurationPackages Gets the configurationpackages of the


company.

automationCompanies automationCompanies Gets the automationcompanies of the


company.

extensions extensions Gets the extensions of the company.

userGroups userGroups Gets the usergroups of the company.

users users Gets the users of the company.

userGroupMembers userGroupMembers Gets the usergroupmembers of the


company.

userPermissions userPermissions Gets the userpermissions of the


company.

scheduledJobs scheduledJobs Gets the scheduledjobs of the


company.

permissionSets permissionSets Gets the permissionsets of the


company.

extensionUpload extensionUpload Gets the extensionupload of the


company.

extensionDeploymentStatus extensionDeploymentStatus Gets the extensiondeploymentstatus


of the company.
Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the item. Non-


editable.

systemVersion string Specifies the internal version of the


company.

name string Represents the company's name.

displayName string Specifies the company's name. This


name will appear on all sales
documents for the company.

businessProfileId string Specifies the Business Profile ID linked


to the company.

systemCreatedAt datetime The datetime the company was


created.

systemCreatedBy GUID The ID of the user who created the


company.

systemModifiedAt datetime The last datetime the company was


modified.

systemModifiedBy GUID The ID of the user who last modified


the company.

JSON representation
Here is a JSON representation of the company resource.

{
"id": "GUID",
"systemVersion": "string",
"name": "string",
"displayName": "string",
"businessProfileId": "string",
"systemCreatedAt": "datetime",
"systemCreatedBy": "GUID",
"systemModifiedAt": "datetime",
"systemModifiedBy": "GUID"
}

See Also
GET company
Get company
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a company object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET /microsoft/automation/v2.0/companies

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a company object in the response body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment name}/api/microsoft/automation/v2.0/companies

Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.

{
"id": "3496bbf8-fcae-4e48-a4f8-cb17c27de0b3",
"systemVersion": "24012",
"name": "CRONUS USA, Inc.",
"displayName": "CRONUS USA, Inc.",
"businessProfileId": ""
}
See Also
Tips for working with the APIs
company
configurationPackage resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents a configuration package in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET configurationPackage configurationPackage Gets a configuration package object.

DELETE configurationPackage none Deletes a configuration package object.

POST configurationPackage configurationPackage Creates a configuration package


object.

PATCH configurationPackage configurationPackage Updates a configuration package


object.

Bound Actions
The configurationPackage resource type offers a bound action called import which imports the corresponding
configurationPackage batch. This is illustrated in the following example:
POST https://<server address>:<server API port>/<server instance
name>/api/microsoft/automation/v2.0/companies({id})/configurationPackages({id})/Microsoft.NAV.import

The response has no content; the response code is 204.


The configurationPackage resource type offers a bound action called apply which applys the corresponding
configurationPackage batch. This is illustrated in the following example:
POST https://<server address>:<server API port>/<server instance
name>/api/microsoft/automation/v2.0/companies({id})/configurationPackages({id})/Microsoft.NAV.apply

The response has no content; the response code is 204.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the item. Non-


editable.

code string The code of the configuration package.

packageName string Name of the configuration package.


P RO P ERT Y TYPE DESC RIP T IO N

languageId integer Id of the language.

productVersion string Version of the product.

processingOrder integer Specifies the order of processing.

excludeConfigurationTables boolean Specifies whether to exclude


configuration tables.

numberOfTables integer Number of tables.

numberOfRecords integer Number of records.

numberOfErrors integer Number of errors.

importStatus string The status of the import.

importError string The error of an import failure.

applyStatus string Status of configuration package to


apply.

applyError string Error to apply.

JSON representation
Here is a JSON representation of the configurationPackage resource.

{
"id": "GUID",
"code": "string",
"packageName": "string",
"languageId": "integer",
"productVersion": "string",
"processingOrder": "integer",
"excludeConfigurationTables": "boolean",
"numberOfTables": "integer",
"numberOfRecords": "integer",
"numberOfErrors": "integer",
"importStatus": "string",
"importError": "string",
"applyStatus": "string",
"applyError": "string"
}

See Also
GET configurationPackage
DELETE configurationPackage
POST configurationPackage
PATCH configurationPackage
Get configurationPackage
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a configuration package object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET /microsoft/automation/v2.0/companies({companyId})/configurationPackages

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a configurationPackage object in the response
body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/configurationPackages({packageId})

Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.
{
"id": "b6d25c66-f33d-eb11-846f-0022482037e2",
"code": "MyRSPackage",
"packageName": "SAMPLE",
"languageId": 0,
"productVersion": "",
"processingOrder": 0,
"excludeConfigurationTables": false,
"numberOfTables": 12,
"numberOfRecords": 3,
"numberOfErrors": 3,
"importStatus": "Completed",
"applyStatus": "Completed",
"applyError": "",
"importError": ""
}

See Also
Tips for working with the APIs
configurationPackage
Delete configurationPackage
2/6/2023 • 2 minutes to read • Edit Online

Deletes a configuration package from Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

DELETE /microsoft/automation/v2.0/companies({companyId})/configurationPackages({packageId})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
configurationPackage , the configurationPackage will
not be updated.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns 204 No Content response code and deletes the configurationPackage. It does
not return anything in the response body.

Example
Request
Here is an example of the request.

DELETE https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/configurationPackages({packageId})

Response
Here is an example of the response.

HTTP/1.1 204 No Content

See Also
Tips for working with the APIs
configurationPackage
Create configurationPackage
2/6/2023 • 2 minutes to read • Edit Online

Creates a configuration package in Dynamics 365 Business Central.

Bound Actions
A C T IO N S RET URN T Y P E DESC RIP T IO N

Microsoft.NAV.import none Imports a configurationPackage.

Microsoft.NAV.apply none Applies a configurationPackage.

HTTP requests
Replace the URL prefix for Business Central depending on environment following the guideline.
Insert configurationPackage

POST /microsoft/automation/v2.0/companies({companyId})/configurationPackages
Content-type: application/json
{
"code":"YourPackageCode",
"packageName": "YourPackageName"
}

Response
If successful, this method returns 201 Created response code and a configurationPackage object in the
response body.
Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

Request body
In the request body, supply a JSON representation of a configurationPackage object.
Import configurationPackage

POST
/microsoft/automation/v2.0/companies({companyId})/configurationPackages({packageId})/Microsoft.NAV.import

Apply configurationPackage
POST
/microsoft/automation/v2.0/companies({companyId})/configurationPackages({packageId})/Microsoft.NAV.apply

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.
Response
If successful, this method returns 204 No Content response code.

Example
Request
Here is an example of the request.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/configurationPackages
Content-type: application/json
{
"code":"YourPackageCode",
"packageName": "YourPackageName"
}

Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.

HTTP/1.1 201 Created


Content-type: application/json
{
"id": "b6d25c66-f33d-eb11-846f-0022482037e2",
"code": "YourPackageCode",
"packageName": "YourPackageName",
"languageId": 0,
"productVersion": "",
"processingOrder": 0,
"excludeConfigurationTables": false,
"numberOfTables": 12,
"numberOfRecords": 3,
"numberOfErrors": 3,
"importStatus": "Completed",
"applyStatus": "Completed",
"applyError": "",
"importError": ""
}
See Also
Tips for working with the APIs
configurationPackage
Update configurationPackage
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of a configuration package object for Dynamics 365 Business Central.

HTTP request
Upload RapidStart package

PATCH
/microsoft/automation/v2.0/companies({companyId})/configurationPackages({packageId})/file('{packageCode}')/c
ontent
Content-type: application/octet-stream
Body: binary content of the RapidStart package

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
configurationPackage , the configuration package will
not be updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 204 No Content .

Example
Request
Here is an example of the request.
PATCH https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/configurationPackages({packageId})/file('{package
Code}')/content
Authorization : Bearer {token}
Content-type : application/octet-stream
If-Match:*
Body: binary stream

See Also
Tips for working with the APIs
configurationPackage
extension resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents an extension in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET extension extension Gets a extension object.

Bound Actions
The extension resource type offers a bound action called install which installs the corresponding extension
batch. This is illustrated in the following example:
POST https://<server address>:<server API port>/<server instance
name>/api/v2.0/companies({id})/extensions({id})/Microsoft.NAV.install

The response has no content; the response code is 204.


The extension resource type offers a bound action called uninstall which uninstalls the corresponding
extension batch. This is illustrated in the following example:
POST https://<server address>:<server API port>/<server instance
name>/api/v2.0/companies({id})/extensions({id})/Microsoft.NAV.uninstall

The response has no content; the response code is 204.


The extension resource type offers a bound action called uninstallAndDeleteExtensionData which uninstalls the
corresponding extension batch and deletes the tables that contain data owned by the extension on uninstall. This
action cannot be undone. This is illustrated in the following example:
POST https://<server address>:<server API port>/<server instance
name>/api/v2.0/companies({id})/extensions({id})/Microsoft.NAV.uninstallAndDeleteExtensionData

The response has no content; the response code is 204.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

packageId GUID The unique ID of the package. Read-


Only.

id GUID The unique ID of the item. Non-


editable.
P RO P ERT Y TYPE DESC RIP T IO N

displayName string Specifies the extension's name. This


name will appear on all sales
documents for the extension.

publisher string Specifies the publisher of the


extension.

versionMajor integer Major version of the extension.

versionMinor integer Minor version of the extension.

versionBuild integer The version of the build.

versionRevision integer The version revision of the extension.

isInstalled boolean Specifies the installation status.

publishedAs string Specifies how the compiled extension


was published.

JSON representation
Here is a JSON representation of the extension resource.

{
"packageId": "GUID",
"id": "GUID",
"displayName": "string",
"publisher": "string",
"versionMajor": "integer",
"versionMinor": "integer",
"versionBuild": "integer",
"versionRevision": "integer",
"isInstalled": "boolean",
"publishedAs": "string"
}

See Also
GET extension
Get extension
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of an extension object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET /microsoft/automation/v2.0/companies({companyid})/extensions({packageId})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and an extension object in the response body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/extensions({packageId})

Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.
{
"packageId": "3252be43-93d6-4d6a-b603-cdc0f0f32a9e",
"id": "3d5b2137-efeb-4014-8489-41d37f8fd4c3",
"displayName": "Late Payment Prediction",
"publisher": "Microsoft",
"versionMajor": 18,
"versionMinor": 0,
"scope": 0,
"isInstalled": true
}

See Also
Tips for working with the APIs
extension
extensionDeploymentStatus resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents an extension deployment status in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET extensionDeploymentStatus extensionDeploymentStatus Gets a extension deployment status


object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

operationID GUID The unique ID of the operation.

name string Represents the extension deployment


status's name.

publisher string Specifies the publisher of the


extension.

operationType string Specifies the operation.

status string Specifies the status of the extension


deployment status.

schedule string Specifies the schedule for installation.

appVersion string The version of the App.

startedOn datetime Timestamp for the initialization of the


operation.

JSON representation
Here is a JSON representation of the extensionDeploymentStatus resource.
{
"operationID": "GUID",
"name": "string",
"publisher": "string",
"operationType": "string",
"status": "string",
"schedule": "string",
"appVersion": "string",
"startedOn": "datetime"
}

See Also
GET extensionDeploymentStatus
Get extensionDeploymentStatus
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of an extension deployment status object for Dynamics 365 Business
Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET /microsoft/automation/v2.0/companies({companyId})/extensionDeploymentStatus

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and an extensionDeploymentStatus object in the
response body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/extensionDeploymentStatus

Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.
{
"operationID": "138fb013-1ebd-4e65-a333-420631e67344",
"name": "VeryNiceApp",
"publisher": "Default publisher",
"operationType": "Upload",
"status": "Completed",
"schedule": "Immediate",
"appVersion": "1.0.0.0",
"startedOn": "2018-08-23T09:07:04.387Z"
}

See Also
Tips for working with the APIs
extensionDeploymentStatus
extensionUpload resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents an extension upload in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET extensionUpload extensionUpload Gets a extension upload object.

POST extensionUpload extensionUpload Creates a extension upload object.

PATCH extensionUpload extensionUpload Updates a extension upload object.

Bound Actions
The extensionUpload resource type offers a bound action called upload which uploads the corresponding
extensionUpload batch. This is illustrated in the following example:
POST https://<server address>:<server API port>/<server instance
name>/api/microsoft/automation/v2.0/companies({id})/extensionUpload({id})/Microsoft.NAV.upload

The response has no content; the response code is 204.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

systemId GUID The unique ID of the system.

schedule string Specifies the schedule for installation.


Values can be "Current version", "Next
minor version", or "Next major version".

schemaSyncMode string Specifies the schema sync mode for


installation. Values can be "Add" or
"Force Sync"

extensionContent stream The content of the extension.

JSON representation
Here is a JSON representation of the extensionUpload resource.
{
"systemId": "GUID",
"schedule": "string",
"schemaSyncMode": "string",
"extensionContent": "stream"
}

See Also
GET extensionUpload
POST extensionUpload
PATCH extensionUpload
Get extensionUpload
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of an extension upload object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET /microsoft/automation/v2.0/companies({companyId})/extensionUpload({extensionUploadId})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and an extensionUpload object in the response
body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/extensionUpload({extensionUploadId})

Response Here is an example of the response.

{
"systemId" : "f99be650-07ce-45df-a285-3afe69a953eb",
"schedule" : "Next major version",
"schemaSyncMode": "Add",
"extensionContent" : ""
}

Schedule in the body can be "Current version", "Next minor version", or "Next major version". Schema Sync
Mode in the body can be "Add" or "Force Sync".

See Also
Tips for working with the APIs
extensionUpload
Create extensionUpload
2/6/2023 • 2 minutes to read • Edit Online

Creates an extension upload in Dynamics 365 Business Central.

Bound Actions
A C T IO N S RET URN T Y P E DESC RIP T IO N

Microsoft.NAV.upload none Uploads an extension.

HTTP requests
Replace the URL prefix for Business Central depending on environment following the guideline.
Insert extensionUpload

POST /microsoft/automation/v2.0/companies({companyId})/extensionUpload

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

Request body
In the request body, supply a JSON representation of a extensionUpload object.
Response
If successful, this method returns 201 Created response code and a extensionUpload object in the response
body.
Upload extensionUpload

POST
/microsoft/automation/v2.0/companies({companyId})/extensionUpload({extensionUploadId})/Microsoft.NAV.upload

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.
Response
If successful, this method returns 204 No Content response code.

Example
Request
Here is an example of the request.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/extensionUpload
Content-type: application/json
{
"schedule" : "Current version",
"schemaSyncMode": "Add"
}

Response Here is an example of the response.

HTTP/1.1 201 Created


Content-type: application/json
{
"systemId" : "f99be650-07ce-45df-a285-3afe69a953eb",
"schedule" : "Current version",
"schemaSyncMode": "Add",
"extensionContent" : ""
}

See Also
Tips for working with the APIs
extensionUpload
Update extensionUpload
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of an extension upload object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

PATCH /microsoft/automation/v2.0/companies({companyId})/extensionUpload({extensionUploadId})/content
Content-type: application/octet-stream
Body: binary content of the extension

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/octet-stream

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
extensionUpload , the extension upload will not be
updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 204 No Content .

Example
Request Here is an example of the request.

PATCH https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/extensionUpload({extensionUploadId})/content
Authorization : Bearer {token}
Content-type : application/octet-stream
If-Match:-*
Body: binary stream

See Also
Tips for working with the APIs
extensionUpload
permissionSet resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents a permission set in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET permissionSet permissionSet Gets a permission set object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

scope string Scope of the permission set.

appId GUID The ID of the App.

id string The unique ID of the permission set.


Read-Only.

displayName string Specifies the permission set's name.


This name will appear on all sales
documents for the permission set.

extensionName string The name of the extension.

JSON representation
Here is a JSON representation of the permissionSet resource.

{
"scope": "string",
"appId": "GUID",
"id": "string",
"displayName": "string",
"extensionName": "string"
}

See Also
GET permissionSet
Get permissionSet
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a permission set object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET /microsoft/automation/v2.0/companies({companyId})/permissionSets

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a permissionSet object in the response body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/permissionSets

Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.
{
"id": "D365 ACC. PAYABLE",
"scope": "System",
"appID": "00000000-0000-0000-0000-000000000000",
"displayName": "Dynamics 365 Accounts payable",
"extensionName": ""
}

See Also
Tips for working with the APIs
permissionSet
scheduledJob resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents a scheduled job by API's in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET scheduledJob scheduledJob Gets a scheduled job object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the item. Non-


editable.

category string Specifies the category of the scheduled


job.

status string Specifies the status of the scheduled


job.

description string Specifies the description of the


scheduled job.

errorMessage string The error message provided when a


fail occurs.

JSON representation
Here is a JSON representation of the scheduledJob resource.

{
"id": "GUID",
"category": "string",
"status": "string",
"description": "string",
"errorMessage": "string"
}

See Also
GET scheduledJob
Get scheduledJob
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a scheduled job object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET /microsoft/automation/v2.0/companies({companyId})/scheduledJobs({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a scheduledJob object in the response body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/scheduledJobs({id})

Response Here is an example of the response.

{
"id" : "26066f96-8775-eb11-bb56-000d3a298ab3",
"category" : "APIUSERJOB",
"status" : "In Progress",
"description" : "Create new users from Azure AD API job",
"errorMessage" : ""
}

See Also
Tips for working with the APIs
scheduledJob
user resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents an user in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET user user Gets a user object.

PATCH user user Updates a user object.

Bound Actions
The user resource type offers a bound action called getNewUsersFromOffice365 which retrieves new users or new
user information from the Office 365 portal. Note that existing, unchanged users will not be updated. This is
illustrated in the following example:
POST https://<server address>:<server API port>/<server instance
name>/api/microsoft/automation/v2.0/companies({id})/users({id})/Microsoft.NAV.createNewUsersFromAzureAD

The response has no content; the response code is 204.


The user resource type offers a bound action called getNewUsersFromOffice365Async which schedules a
background job to retrieve new users or new user information from the Office 365 portal. Note that existing,
unchanged users will not be updated. This is illustrated in the following example:
POST https://<server address>:<server API port>/<server instance
name>/api/microsoft/automation/v2.0/companies({id})/users({id})/Microsoft.NAV.createNewUsersFromAzureADAsync

The response has a reference to the scheduled job to track the progress of the scheduled background job; the
response code is 201.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

userGroupMembers userGroupMembers Gets the usergroupmembers of the


user.

userPermissions userPermissions Gets the userpermissions of the user.

scheduledJobs scheduledJobs Gets the scheduledjobs of the user.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

userSecurityId GUID The unique ID of the user security.

userName string Specifies the user name.

displayName string Specifies the user's name. This name


will appear on all sales documents for
the user.

state string Specifies the user's state.

expiryDate datetime The date of expiration.

JSON representation
Here is a JSON representation of the user resource.

{
"userSecurityId": "GUID",
"userName": "string",
"displayName": "string",
"state": "string",
"expiryDate": "datetime"
}

See Also
GET user
PATCH user
Get user
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of an user object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET /microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and an user object in the response body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyid})/users({userSecurityId})

Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.
{
"userSecurityId": "82ae94d5-3445-47de-8668-714b5113a9c2",
"userName": "JOE",
"displayName": "JOE JONES",
"state": "Enabled",
"expiryDate": "0001-01-01T00:00:00Z"
}

See Also
Tips for working with the APIs
user
Update user
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of an user object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

PATCH /microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the user , the
user will not be updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 200 OK response code and an updated **user ** object in the response
body.

Example
Request
Here is an example of the request.

PATCH https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})
Content-type: application/json
If-Match:*
{
"state": "Enabled",
"expiryDate": "2035-01-01T21:03:53.444Z"
}

Response Here is an example of the response.


HTTP/1.1 200 OK
Content-type: application/json
{
"userSecurityId": "7ae30772-481f-4895-a042-98f36e280680",
"userName": "JOE",
"displayName": "JOE JONES",
"state": "Enabled",
"expiryDate": "2035-01-01T21:03:53.443Z"
}

See Also
Tips for working with the APIs
user
userGroup resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents an user group in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET userGroup userGroup Gets a user group object.

DELETE userGroup none Deletes a user group object.

POST userGroup userGroup Creates a user group object.

PATCH userGroup userGroup Updates a user group object.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

userGroupPermissions userGroupPermissions Gets the permissions of the


userGroup.

profile profile Gets the profile of the userGroup.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the user group. Non-


editable.

code string The code of the user group.

displayName string Specifies the user group's name. This


name will appear on all sales
documents for the user group.

defaultProfileID string The ID of the defaultProfile.

assignToAllNewUsers boolean If true, all new users are assigned to


user group.
JSON representation
Here is a JSON representation of the userGroup resource.

{
"id": "GUID",
"code": "string",
"displayName": "string",
"defaultProfileID": "string",
"assignToAllNewUsers": "boolean"
}

See Also
GET userGroup
DELETE userGroup
POST userGroup
PATCH userGroup
Get userGroup
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of an user group object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET /microsoft/automation/v2.0/companies({companyId})/userGroups({userGroupId})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and an userGroup object in the response body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/userGroups({userGroupId})

Response Here is an example of the response.

{
"id": "d38a92e2-9d74-eb11-bb5c-00155df3a615",
"code": "D365 ACCOUNTANTS",
"displayName": "Dynamics 365 for Accountants",
"defaultProfileID": "ACCOUNTANT PORTAL",
"assignToAllNewUsers": false
}

See Also
Tips for working with the APIs
userGroup
Create userGroup
2/6/2023 • 2 minutes to read • Edit Online

Creates a user group in Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

POST /microsoft/automation/v2.0/companies({companyId})/userGroups

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

Request body
In the request body, supply a JSON representation of a userGroup object.

Response
If successful, this method returns 201 Created response code and a userGroup object in the response body.

Example
Request
Here is an example of the request.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/userGroups
Content-type: application/json
{
"code": "NEW USER GROUP",
"displayName": "New User Group",
"defaultProfileID": "ACCOUNTANT"
}

Response Here is an example of the response.


HTTP/1.1 201 Created
Content-type: application/json
{
"id": "90814d0b-caad-eb11-9b52-000d3ab03e45",
"code": "NEW USER GROUP",
"displayName": "New User Group",
"defaultProfileID": "ACCOUNTANT",
"assignToAllNewUsers": false
}

See Also
Tips for working with the APIs
userGroup
Delete userGroup
2/6/2023 • 2 minutes to read • Edit Online

Deletes a user group from Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

DELETE /microsoft/automation/v2.0/companies({companyId})/userGroups({userGroupId})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
userGroup , the userGroup will not be updated.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns 204 No Content response code and deletes the userGroup. It does not return
anything in the response body.

Example
Request
Here is an example of the request.

DELETE https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/userGroups({userGroupId})

Response
Here is an example of the response.

HTTP/1.1 204 No Content

See Also
Tips for working with the APIs
userGroup
Update userGroup
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of an user group object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

PATCH /microsoft/automation/v2.0/companies({companyId})/userGroups({userGroupId})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
userGroup , the user group will not be updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 200 OK response code and an updated userGroup object in the response
body.

Example
Request
Here is an example of the request.

PATCH https:///microsoft/automation/{apiVersion}/companies({companyId})/userGroups({userGroupId})
Content-type: application/json
{
"displayName" : "YourUserGroupName"
}

Response Here is an example of the response.


HTTP/1.1 200 OK
Content-type: application/json
{
"id": "d38a92e2-9d74-eb11-bb5c-00155df3a615",
"code": "D365 ACCOUNTANTS",
"displayName": "YourUserGroupName",
"defaultProfileID": "ACCOUNTANT PORTAL",
"assignToAllNewUsers": false
}

See Also
Tips for working with the APIs
userGroup
userGroupMember resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents an user group member in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET userGroupMember userGroupMember Gets a user group member object.

DELETE userGroupMember none Deletes a user group member object.

POST userGroupMember userGroupMember Creates a user group member object.

PATCH userGroupMember userGroupMember Updates a user group member object.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

user user Gets the user of the


userGroupMember.

userGroup userGroup Gets the usergroup of the


userGroupMember.

automationCompany automationCompany Gets the automationcompany of the


userGroupMember.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the user group


member.

userSecurityId GUID The unique ID of the user security.

code string The code of the user group member.


P RO P ERT Y TYPE DESC RIP T IO N

displayName string Specifies the user group member's


name. This name will appear on all
sales documents for the user group
member.

companyName string The name of the company.

JSON representation
Here is a JSON representation of the userGroupMember resource.

{
"id": "GUID",
"userSecurityId": "GUID",
"code": "string",
"displayName": "string",
"companyName": "string"
}

See Also
GET userGroupMember
DELETE userGroupMember
POST userGroupMember
PATCH userGroupMember
Get userGroupMember
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of an user group member object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET
/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userGroupMembers({userGroupMemberI
d})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and an userGroupMember object in the response
body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userGroupMembers({userGro
upMemberId})

Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.
{
"id": "d38a92e2-9d74-eb11-bb5c-00155df3a615",
"code": "D365 BUS PREMIUM",
"userSecurityId": "7ae30772-481f-4895-a042-98f36e280680",
"companyName": "CRONUS USA, Inc.",
"displayName": "D365 Premium Business Access"
}

See Also
Tips for working with the APIs
userGroupMember
Delete userGroupMember
2/6/2023 • 2 minutes to read • Edit Online

Deletes an user group member from Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

DELETE
/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userGroupMembers({userGroupMemberI
d})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
userGroupMember , the userGroupMember will not be
updated.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns 204 No Content response code and deletes the userGroupMember. It does not
return anything in the response body.

Example
Request
Here is an example of the request.

DELETE https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userGroupMembers({userGro
upMemberId})
If-Match:*

Response
Here is an example of the response.

HTTP/1.1 204 No Content


See Also
Tips for working with the APIs
userGroupMember
Create userGroupMember
2/6/2023 • 2 minutes to read • Edit Online

Creates an user group member in Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

POST /microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userGroupMembers

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

Request body
In the request body, supply a JSON representation of a userGroupMember object.

Response
If successful, this method returns 201 Created response code and a userGroupMember object in the response
body.

Example
Request
Here is an example of the request.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userGroupMembers
Content-Type:application/json
{
"id": "d38a92e2-9d74-eb11-bb5c-00155df3a615",
"code": "D365 EXT. ACCOUNTANT",
"companyName" :"CRONUS USA, Inc."
}

Response
Here is an example of the response.
NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.

{
"id": "d38a92e2-9d74-eb11-bb5c-00155df3a615",
"code": "D365 EXT. ACCOUNTANT",
"userSecurityId": "7ae30772-481f-4895-a042-98f36e280680",
"companyName": "CRONUS USA, Inc.",
"displayName": ""
}

See Also
Tips for working with the APIs
userGroupMember
Update userGroupMember
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of an user group member object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

PATCH
/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userGroupMembers({userGroupMemberI
d})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
userGroupMember , the user group member will not be
updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 200 OK response code and an updated **userGroupMember ** object in the
response body.

Example
Request
Here is an example of the request.
PATCH https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userGroupMembers({userGro
upMemberId})

Content-type: application/json
{
"displayName": "YourDisplayName"
}

Response Here is an example of the response.

HTTP/1.1 200 OK
Content-type: application/json
{
"id": "d38a92e2-9d74-eb11-bb5c-00155df3a615",
"code": "D365 BUS PREMIUM",
"userSecurityId": "7ae30772-481f-4895-a042-98f36e280680",
"companyName": "CRONUS USA, Inc.",
"displayName": "YourDisplayName"
}

See Also
Tips for working with the APIs
userGroupMember
userPermission resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents an user permission in Dynamics 365 Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET userPermission userPermission Gets a user permission object.

DELETE userPermission none Deletes a user permission object.

POST userPermission userPermission Creates a user permission object.

PATCH userPermission userPermission Updates a user permission object.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

user user Gets the user of the userPermission.

permissionSet permissionSet Gets the permissionset of the


userPermission.

automationCompany automationCompany Gets the automationcompany of the


userPermission.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the user permission.


Read-Only.

userSecurityId GUID The unique ID of the user security.

roleId string The unique ID of the user permission


role.

displayName string Specifies the user permission's name.


This name will appear on all sales
documents for the user permission.
P RO P ERT Y TYPE DESC RIP T IO N

company string The company name.

appId GUID The ID of the App.

extensionName string The name of the extension.

scope string Scope of the user permission.

JSON representation
Here is a JSON representation of the userPermission resource.

{
"id": "GUID",
"userSecurityId": "GUID",
"roleId": "string",
"displayName": "string",
"company": "string",
"appId": "GUID",
"extensionName": "string",
"scope": "string"
}

See Also
GET userPermission
DELETE userPermission
POST userPermission
PATCH userPermission
Get userPermission
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of an user permission object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userPermissions({userPermissionId}
)

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and an userPermission object in the response body.

Example
Request
Here is an example of the request.

GET https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userPermissions({userPerm
issionId})

Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.
{
"id": "d38a92e2-9d74-eb11-bb5c-00155df3a615",
"userSecurityId": "a0ad6d24-99b7-440e-a26d-9a86840c2056",
"roleId": "SUPER",
"company": "",
"scope": "System",
"appId": "00000000-0000-0000-0000-000000000000",
"displayName": "This role has all permissions.",
"extensionName": ""

See Also
Tips for working with the APIs
userPermission
Delete userPermission
2/6/2023 • 2 minutes to read • Edit Online

Deletes an user permission from Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

DELETE
/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userPermissions({userPermissionId}
)

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
userPermission , the userPermission will not be updated.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns 204 No Content response code and deletes the userPermission. It does not
return anything in the response body.

Example
Request
Here is an example of the request.

DELETE https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userPermissions({userPerm
issionId})
If-Match:*

Response
Here is an example of the response.

HTTP/1.1 204 No Content


See Also
Tips for working with the APIs
userPermission
Create userPermission
2/6/2023 • 2 minutes to read • Edit Online

Creates an user permission in Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

POST /microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userPermissions

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

Request body
In the request body, supply a JSON representation of a userPermission object.

Response
If successful, this method returns 201 Created response code and a userPermission object in the response
body.

Example
Request
Here is an example of the request.

POST https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userPermissions
Content-Type:application/json
{
"roleId": "SECURITY",
"company" : "CRONUS"
}

Response
Here is an example of the response.
NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.

{
"id": "d38a92e2-9d74-eb11-bb5c-00155df3a615",
"userSecurityId": "82ae94d5-3445-47de-8668-714b5113a9c2",
"roleId": "SECURITY",
"company": "CRONUS",
"scope": "System",
"appID": "00000000-0000-0000-0000-000000000000",
"displayName": "",
"extensionName": ""
}

See Also
Tips for working with the APIs
userPermission
Update userPermission
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of an user permission object for Dynamics 365 Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

PATCH
/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userPermissions({userPermissionId}
)

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
userPermission , the user permission will not be updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 200 OK response code and an updated **userPermission ** object in the
response body.

Example
Request
Here is an example of the request.

PATCH https://api.businesscentral.dynamics.com/v2.0/{environment
name}/api/microsoft/automation/v2.0/companies({companyId})/users({userSecurityId})/userPermissions({userPerm
issionId})
Content-type: application/json
{
"userSecurityId": "82ae94d5-3445-47de-8668-714b5113a9c2",
"roleId": "SECURITY",
}
Response
Here is an example of the response.

NOTE
The response object shown here may be truncated for brevity. All of the properties will be returned from an actual call.

{
"id": "d38a92e2-9d74-eb11-bb5c-00155df3a615",
"userSecurityId": "82ae94d5-3445-47de-8668-714b5113a9c2",
"roleId": "SECURITY",
"company": "",
"scope": "System",
"appID": "00000000-0000-0000-0000-000000000000",
"displayName": "",
"extensionName": ""
}

See Also
Tips for working with the APIs
userPermission
The Business Central Admin Center API
2/6/2023 • 7 minutes to read • Edit Online

The Business Central administration center API enables administrators to programmatically do administrative
tasks for a Business Central tenant. With the API, administrators can, for example:
Query and work with production and sandbox environments for the tenant.
Set up administrative notifications.
View telemetry for events on the tenant.
For more information about administrative capabilities, see The Business Central Administration Center. This
article describes the API contracts for these administrative capabilities.

IMPORTANT
For delegated admin access, you must add the Azure Active Directory (Azure AD) application to the AdminAgents
group. If the Azure AD application is not added, the consent flow will show an error such as Need pre-consent. For more
information, see Pre-consent your app for all your customers in the Graph documentation.

Location
The Business Central administration center API is located at the following URL:
https://api.businesscentral.dynamics.com.

Authenticate using service-to-service AAD Apps (Client Credentials


Flow)
IMPORTANT
This authentication type is supported from version 20.0 an onwards

The Business Central administration center API supports authentication using AAD Apps.
1. Sign in to the Azure portal.
2. Register an application for Business Central administration center in your Azure Active Directory tenant.
Follow the general guidelines at Register your application with your Azure Active Directory tenant.
When you add an application to an Azure AD tenant, you must specify the following information:

SET T IN G DESC RIP T IO N

Name Specify a unique name for your application.

Supported account types Select either Accounts in this organizational


director y only (Microsoft only - Single tenant) or
Accounts in any organizational director y (Any
Azure AD director y - Multitenant) .
SET T IN G DESC RIP T IO N

Redirect URI Optional. You can grant consent from the Azure portal if
left empty.

When completed, an Over view displays in the portal for the new application.
3. Create a client secret for the registered application as follows:
a. Select Cer tificates & secrets > New client secret .
b. Add a description, select a duration, and select Add .

NOTE
Copy the secret's value for use in your client application code. This secret value is never displayed again after you
leave this page.

For the latest guidelines about adding client secrets in Azure AD, see Add credentials in the Azure
documentation.

NOTE
Copy the Application (client) ID of the registered app. You'll need this later. You can get this value from the Over view
page.

4. Grant the registered application AdminCenter.ReadWrite.All permission to the Dynamics 365


Business Central administration center API as follows:
a. Select API permissions > Add a permission > Microsoft APIs .
b. Select Dynamics 365 Business Central .
c. Select Application permissions , select AdminCenter.ReadWrite.All , then select Add
permissions .

NOTE
If you intent to use the same AAD App with the Automation API and Business Central Web Services you can also
grant API.ReadWrite.All and Automation.ReadWrite.All permissions. Learn more here.

5. (optional) Grant admin consent on each permission by selecting it in the list, then selecting Grant admin
consent for <tenant name> . This step isn't required if you'll be granting consent from the Business
Central administration center. It is possible to grant consent from this page only for your own current
tenant. This works for single-tenant apps, but for multi-tenant apps you have to grant consent for each
tenant from that tenant's Azure AD portal or the Business Central administration center
6. Go to the Business Central administration center and navigate to the 'Authorized AAD Apps' page. Paste
the Application (client) ID of your app in the form to authorize an app.
7. If not already completed in step 5 you can grant consent for your app from the 'Authorized AAD Apps'
page in the Business Central administration center.
Note: There might be a short delay until the Granted status is visible in the TAC UI after refreshing.
8. (optional) Some operations in the Business Central administration center API require that the app has a
permissions assigned in the environment in addition to the authorization in the Business Central
administration center. Follow the instructions in Task 2 here to assign permissions.
NOTE
Learn more about permissions required for App Management operations here and learn more about permissions
required for Database Exports here.

Getting an Access Token with Client Credentials Flow


HTTP requests sent to the Business Central administration center API must include the Authorization HTTP
header, and the value must be an access token.
The following examples show how to obtain such a token using PowerShell. Using C# is straightforward.
PowerShell example without prompt:

$cred = [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential]::new($AppId, $AppSecret)


$ctx =
[Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new("https://login.windows.net/$Ten
antName")
$token = $ctx.AcquireTokenAsync("996def3d-b36c-4153-8607-a6fd3c01b89f",
$cred).GetAwaiter().GetResult().AccessToken

NOTE
In the PowerShell example above, the guid specified to acquire the token (996def3d-b36c-4153-8607-a6fd3c01b89f) is
the resource ID of Business Central. The example gets the client credential using the app secret, but the recommended
way would be to rely on X.509 certificates.

Calling Business Central administration center API OAuth2Flows


After the Azure AD Application has been set up, authorized in the Business Central administration center, and
granted admin consent, you're ready to make API calls.
The following sample uses the Rest Client for Visual Studio Code. Using the Rest Client makes it easy to see
which HTTP calls are made both against Business Central and Azure Active Directory. Any HTTP client can be
used to create the requests below. Or you can choose any library, like MSAL.
@tenantId = <tenant id>
@clientId = <client id>
@clientSecret = <client secret>
@baseUri = https://api.businesscentral.dynamics.com
@scope = {{baseUri}}/.default
@url = {{baseUri}}/admin/v2.15

# @name auth
POST https://login.microsoftonline.com/{{tenantId}}/oauth2/v2.0/token HTTP/1.1
Content-type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id={{clientId}}
&client_secret={{clientSecret}}
&scope={{scope}}

### Variable Response


@accessHeader = Bearer {{auth.response.body.$.access_token}}

# @name GetEnvironments
GET {{url}}/applications/BusinessCentral/environments HTTP/1.1
Authorization: {{accessHeader}}

### Variable Response


@environmentName = {{GetEnvironments.response.body.value.[0].name}}

Setting up Azure Active Directory (Azure AD) based authentication


(Authorization Code Flow)
Sign in to the Azure portal to register your client application as an app and enable it to call the Business Central
administration center API.
1. Follow the instructions in the Integrating applications with Azure Active Directory article. The next steps
elaborate on some of the specific settings you must enable.
2. Give the application a Name , such as Business Central Web Ser vice Client .
3. For Application type , choose either Native or Web app/API depending on your scenario. The code
examples below assume Native .
4. Choose a Redirect URI . If it's a Native app, you can choose for example:
BusinessCentralWebSer viceClient://auth . If it's a Web app/API app, set the value to the actual URL of
the web application.
5. During the registration of the app, make sure to go to Settings , and then under API ACCESS , choose
Required permissions . Choose Add , and then under Add API Access , choose Select an API and search
for the Dynamics 365 Business Central option. Choose Dynamics 365 Business Central , select
Delegated permissions , and then choose the Done button.

NOTE
If Dynamics 365 Business Central doesn't show up in search, it's because the tenant doesn't have any
knowledge of Dynamics 365 Business Central. To make it visible, an easy way is to register for a free trial for
Dynamics 365 Business Central with a user from the directory.

6. Make a note of both the Application ID and the Redirect URI . They'll be needed later.
Getting an access token with Authorization Code Flow
HTTP requests sent to the Business Central administration center API must include the Authorization HTTP
header, and the value must be an access token.
The following examples show how to obtain such a token using PowerShell. Using C# is straightforward.
PowerShell example without prompt:

$cred = [Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential]::new($UserName,
$Password)
$ctx =
[Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new("https://login.windows.net/$Ten
antName")
$token =
[Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireToke
nAsync($ctx, "https://api.businesscentral.dynamics.com", <Application ID>,
$cred).GetAwaiter().GetResult().AccessToken

PowerShell example with prompt:

$ctx =
[Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new("https://login.windows.net/$ten
antName")
$redirectUri = New-Object -TypeName System.Uri -ArgumentList <Redirect URL>
$platformParameters = New-Object -TypeName
Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters -ArgumentList
([Microsoft.IdentityModel.Clients.ActiveDirectory.PromptBehavior]::Always)
$token = $ctx.AcquireTokenAsync("https://api.businesscentral.dynamics.com", <Application ID>,
$redirectUri, $platformParameters).GetAwaiter().GetResult().AccessToken

Error Format
If an error occurs during the execution of an API method, it will respond back with an error object. While the
specifics of any error will vary from endpoint to endpoint and by the error, the error object returned should
adhere to the following structure. When an error occurs that doesn't fit this structure, it typically indicates that
an error occurred in sending the request or during authentication of the request. For example, it could be that
the API hasn't yet received the request.
Error Response Object:

{
"code": string, // A stable error code describing the type an nature of the error. Ex: EnvironmentNotFound
"message": string, // A message with a readable description of the error and cause. Intended to assist with
debugging or troubleshooting the API, it's not intended to be displayed.
("target": string), // Optional - Provides information about what part of a request caused the error. Ex:
The name of a property on the request body.
("extensionData": {...}), // Optional - A key/value dictionary object containing additional information
about the error.
("clientError": [ // Optional - A nested list of error objects containing more details about the error
encountered. For instance, this may be used if multiple errors are encountered to list them all out.
{
"code": string,
"message": string,
"target": string,
"extensionData": {...},
"clientError": [...]
})
]
}

General unhandled errors


All unknown and unhandled errors that aren't covered by the lists above will use the error code: Unknown
See Also
Manage Apps
Microsoft Dynamics 365 Business Central Server Administration Tool
Cloud Migration APIs Overview (v1.0)
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 1 and later

Cloud Migration APIs provide capability for automating the cloud migration process end-to-end by using APIs.
You will be able to complete the setup, move the data, and track the progress, trigger upgrade if needed and
switch off the cloud migration.
The main endpoint for the API is:
https://api.businesscentral.dynamics.com/v2.0/79dbd222-0f30-42a6-9f25-
3164d21b269a/Production/api/microsoft/cloudMigration/v1.0/companies

Set up cloud migration


To create the set up you can issue a POST request, if it is a first setup, otherwise use a PATCH request. Issue the
request against the following endpoint:

POST https://api.businesscentral.dynamics.com/v2.0/{aadTenantID}/{environment
name}/api/microsoft/cloudMigration/v1.0/companies({companyId})/setupCloudMigration
Authorization: Bearer {token}
Content-type: application/json

Body:
{
"productId":"{ProductID}",
"sqlServerType":"{SqlServerType}",
"sqlConnectionString":"{SqlConnectionString}"
}

In the JSON example above, productId can be one of following values:


DynamicsBCLast – use for cloud migration with upgrade
DynamicsBC – use for cloud migration from the same version of Business Central
DynamicsGP – use if you are setting up a Dynamics GP cloud migration
In the JSON example above, sqlServerType can be one of the following values:
SQLServer – Use if you are migrating from the database that is hosted on the On-Prem SQL server
AzureSQL – If you have uploaded the database to migrate to Azure SQL server
And the SqlConnectionString must be the SQL connection string to the database you want to migrate
The above request will return a payload like:

{
"id":"{SetupRecordId}",
"productId":"{ProductID}",
"sqlServerType":"{SqlServerType}",
"sqlConnectionString":"{SqlConnectionString}"
"runtimeName":"{RuntimeName}",
"runtimeKey":"{RuntimeKey}"
}
If you are migrating from Azure SQL you can skip next step:
If you are migrating from SQLServer, you should take the runtimeKey value and install and connect Microsoft
Integration Runtime by using this key. Then you need to issue a PATCH request such as the following:

PATCH https://api.businesscentral.dynamics.com/v2.0/{aadTenantID}/{environment
name}/api/microsoft/cloudMigration/v1.0/companies({companyId})/setupCloudMigration({SetupRecordId})
Authorization: Bearer {token}
Content-type: application/json
If-Match: etag
Body:
{
"productId":"{ProductID}",
"sqlServerType":"{SqlServerType}",
"sqlConnectionString":"{SqlConnectionString}",
"runtimeName":"{RuntimeName}"
}

To complete the setup for both SQL and Azure SQL hosted databases invoke:

POST https://api.businesscentral.dynamics.com/v2.0/{aadTenantID}/{environment
name}/api/microsoft/cloudMigration/v1.0/companies({companyId})/setupCloudMigration({SetupRecordId})/
Microsoft.NAV.completeSetup

Cloud migration - create companies


To create on-prem companies you can get the list first by issuing a request like this:

GET https://api.businesscentral.dynamics.com/v2.0/{aadTenantID}/{environment
name}/api/microsoft/cloudMigration/v1.0/companies({companyId})/cloudMigrationCompanies
Authorization: Bearer {token}

The response will be like this for each of the companies:


{
"id": "{CompanyId}",
"name": "{CompanyName}",
"replicate": false,
"displayName": "{DislpayName}",
"estimatedSize":{SizeOfComapny},
"status": "",
"created": false
}

To include the company into the cloud migration you should issue following request:

PATCH https://api.businesscentral.dynamics.com/v2.0/{aadTenantID}/{environment
name}/api/microsoft/cloudMigration/v1.0/companies({companyId})/cloudMigrationCompanies ({CompanyId})
Authorization: Bearer {token}
Content-type: application/json
If-Match: etag
{
"replicate": true
}

To exclude the company, issue the same request with a false value.
Once the companies are marked for replication you can create them by running the following request:
POST https://api.businesscentral.dynamics.com/v2.0/{aadTenantID}/{environment
name}/api/microsoft/cloudMigration/v1.0/companies({companyId})/cloudMigrationCompanies({AnyCompanyId})
/Microsoft.NAV.createCompaniesMarkedForReplication

Authorization: Bearer {token}

DELETE and POST are not allowed against this API; it is not possible to create or delete entities on this API.

Cloud migration status


To manage cloud migration or to track the status this API should be used:

GET https://api.businesscentral.dynamics.com/v2.0/{aadTenantID}/{environment
name}/api/microsoft/cloudMigration/v1.0/companies({companyId})/cloudMigrationStatus
Authorization: Bearer {token}

It will return the following payload:

{
"id": "679c8aa5-16a9-ec11-80f1-002248334988",
"runId": "79090ce4-404d-4274-829a-a3b18e99006c",
"startTime": "2022-03-21T12:57:17Z",
"endTime": "2022-03-21T12:58:48.35Z",
"replicationType": "Normal",
"status": "Completed",
"source": "Dynamics 365 Business Central earlier versions",
"details": "Cloud migration setup completed.",
"tablesSuccessful": 0,
"tablesFailed": 0,
"tablesRemaining": 0
}

To start the replication find the cloudMigrationStatus with last endTime and invoke the following command:

POST https://api.businesscentral.dynamics.com/v2.0/{aadTenantID}/{environment
name}/api/microsoft/cloudMigration/v1.0/companies({companyId})/cloudMigrationStatus ({LastStatusId})
/Microsoft.NAV.runReplication
Authorization: Bearer {token}

To refresh the status do the following request:

POST https://api.businesscentral.dynamics.com/v2.0/{aadTenantID}/{environment
name}/api/microsoft/cloudMigration/v1.0/companies({companyId})/cloudMigrationStatus ({LastStatusId})
/Microsoft.NAV.refreshStatus
Authorization: Bearer {token}

To trigger the data upgrade do the following request:

POST https://api.businesscentral.dynamics.com/v2.0/{aadTenantID}/{environment
name}/api/microsoft/cloudMigration/v1.0/companies({companyId})/cloudMigrationStatus ({LastStatusId})
/Microsoft.NAV.runDataUpgrade
Authorization: Bearer {token}

To disable the replication as the last step do the following request:


POST https://api.businesscentral.dynamics.com/v2.0/{aadTenantID}/{environment
name}/api/microsoft/cloudMigration/v1.0/companies({companyId})/cloudMigrationStatus ({LastStatusId})
/Microsoft.NAV.disableReplication
Authorization: Bearer {token}

See also
Endpoints for the APIs.
cloudMigrationCompany resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents a cloud migration company in Business Central.

NOTE
For information about enabling APIs for Business Central see guideline.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET cloudMigrationCompany cloudMigrationCompany Gets a cloud migration company


object.

PATCH cloudMigrationCompany cloudMigrationCompany Updates a cloud migration company


object.

Bound Actions
The cloudMigrationCompany resource type offers two bound actions:
The first bound action is called createCompaniesMarkedForReplication which create companies marked for
replications the corresponding cloudMigrationCompany batch. This is illustrated in the following example:
CREATECOMPANIESMARKEDFORREPLICATION https://<server address>:<server API port>/<server instance
name>/api/v1.0/companies({id})/cloudMigrationCompanys({id})/Microsoft.NAV.createCompaniesMarkedForReplication

The response has no content; the response code is 204.


The next bound action is called initializeCompany , which is used to initialize the company after cloud migration.
It'll invoke the Codeunit2 Company-Initialize to update missing set up records marked for replications in the
corresponding cloudMigrationCompany batch. This is illustrated in the following example:
INITIALIZECOMPANY https://<server address>:<server API port>/<server instance
name>/api/v1.0/companies({id})/cloudMigrationCompanys({id})/Microsoft.NAV.initializeCompany
.
The response has no content; the response code is 204.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the cloud migration


company. Non-editable.

name string Represents the cloud migration


company's name.
P RO P ERT Y TYPE DESC RIP T IO N

replicate boolean This property decides if the company


should be selected for cloud migration
in the current batch. You can include or
exclude the companies.

displayName string Specifies the cloud migration


company's name. This name will
appear on all sales documents for the
cloud migration company.

estimatedSize decimal Read-Only property representing the


approximate size of the On-Prem
company. The data migrated will be
smaller, since the data will be
compressed and not all tables will be
included.

status string Specifies the status of the company.


Possible values are:
- “ “ – initial status or created. Check
the created property
- “In Progress” – Company creation is
in progress
- Error – Company creation has failed
- "Missing Permission" – User has no
permissions to create a company.

created boolean Specifies if the company was created. It


will not reflect if the setup of the
company was correct or not. For this
you should check the status property.
If the company has been created,
however status is different.

companyInitializationStatus string Specifies the initialization status of the


company. Values are Unknown ,
"Not Initialized" ,
"Initialization Failed" , or
Initialized .

companyInitializationError boolean This property returns an error


message in case the company
initialization fails.

JSON representation
Here is a JSON representation of the cloudMigrationCompany resource.
{
"id": "GUID",
"name": "string",
"replicate": "boolean",
"displayName": "string",
"estimatedSize": "decimal",
"status": "string",
"created": "boolean"
}

See Also
GET cloudMigrationCompany
PATCH cloudMigrationCompany
Get cloudMigrationCompanies
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a cloud migration company object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/cloudMigrationCompanies({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a cloudMigrationCompany object in the
response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v1.0/companies({id})/cloudMigrationCompanies({id})

Response
Here is an example of the response.

{
"id" : "",
"name" : "",
"replicate" : "",
"displayName" : "",
"estimatedSize" : "",
"status" : "",
"created" : ""
}

See Also
Tips for working with the APIs
cloudMigrationCompany
PATCH cloudMigrationCompany
Update cloudMigrationCompanies
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of a cloud migration company object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

PATCH businesscentralPrefix/companies({id})/cloudMigrationCompanies({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
cloudMigrationCompany , the cloud migration
company will not be updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 200 OK response code and an updated cloudMigrationCompany object in
the response body.

Example
Request
Here is an example of the request.

PATCH https://{businesscentralPrefix}/api/v1.0/companies({id})/cloudMigrationCompanies({id})
Content-type: application/json
{
"id" : ,
"name" :
}

Response
Here is an example of the response.

HTTP/1.1 200 OK
Content-type: application/json
{
"id" : ,
"name" : ,
"replicate" : ,
"displayName" : ,
"estimatedSize" : ,
"status" : ,
"created" :
}

See Also
Tips for working with the APIs
cloudMigrationCompany
GET cloudMigrationCompany
cloudMigrationStatus resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents a status record of the cloud migration in Business Central. It is used to start replication, start the data
upgrade, disable the cloud migration, and to track the overall status.

NOTE
For information about enabling APIs for Business Central see guideline.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET cloudMigrationStatus cloudMigrationStatus Gets a cloud migration status object.

Bound Actions
The cloudMigrationStatus resource type offers a bound action called disableReplication which disable
replications the corresponding cloudMigrationStatus batch. This is illustrated in the following example:
DISABLEREPLICATION https://<server address>:<server API port>/<server instance
name>/api/v1.0/companies({id})/cloudMigrationStatus({id})/Microsoft.NAV.disableReplication

The response has no content; the response code is 204.


The cloudMigrationStatus resource type offers a bound action called refreshStatus which refresh statuss the
corresponding cloudMigrationStatus batch. This is illustrated in the following example:
REFRESHSTATUS https://<server address>:<server API port>/<server instance
name>/api/v1.0/companies({id})/cloudMigrationStatus({id})/Microsoft.NAV.refreshStatus

The response has no content; the response code is 204.


The cloudMigrationStatus resource type offers a bound action called resetCloudData which reset cloud datas
the corresponding cloudMigrationStatus batch. This is illustrated in the following example:
RESETCLOUDDATA https://<server address>:<server API port>/<server instance
name>/api/v1.0/companies({id})/cloudMigrationStatus({id})/Microsoft.NAV.resetCloudData

The response has no content; the response code is 204.


The cloudMigrationStatus resource type offers a bound action called runDataUpgrade which run data upgrades
the corresponding cloudMigrationStatus batch. This is illustrated in the following example:
RUNDATAUPGRADE https://<server address>:<server API port>/<server instance
name>/api/v1.0/companies({id})/cloudMigrationStatus({id})/Microsoft.NAV.runDataUpgrade

The response has no content; the response code is 204.


The cloudMigrationStatus resource type offers a bound action called runReplication which run replications the
corresponding cloudMigrationStatus batch. This is illustrated in the following example:
RUNREPLICATION https://<server address>:<server API port>/<server instance
name>/api/v1.0/companies({id})/cloudMigrationStatus({id})/Microsoft.NAV.runReplication

The response has no content; the response code is 204.


Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

cloudMigrationStatusDetails cloudMigrationStatusDetails Gets the cloudmigrationstatusdetails


of the cloudMigrationStatus.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the cloud migration


status. Non-editable.

runId string Specifies the unique ID of the runID.

startTime datetime Specifies the date and time when the


operation was started.

endTime datetime Specifies the date and time when the


operation has ended.

replicationType string Specifies the type of the replication.


Full is for full sync, Normal is usually
representing the delta sync.

status string Specifies the status of the cloud


migration status. Possible values are:
'Failed, In Progress,
Completed,Upgrade Pending, Upgrade
in Progress, Upgrade Failed, Data
Repair Pending'.

source string Specifies the name of the source


product.

details string Specifies the additional details about


this record.

tablesSuccessful integer Specifies the number of tables that was


successfully replicated.

tablesFailed integer Specifies the number of tables that has


failed.

tablesRemaining integer Specifies the number of tables that is


remaining.

estimatedSize decimal Read-Only property representing the


approximate size of the On-Prem
company. The data migrated will be
smaller, since the data will be
compressed and not all tables will be
included.
P RO P ERT Y TYPE DESC RIP T IO N

created boolean Specifies if the company was created. It


will not reflect if the setup of the
company was correct or not. For this
you should check the status property.
If the company has been created,
however status is different.

JSON representation
Here is a JSON representation of the cloudMigrationStatus resource.

{
"id": "GUID",
"runId": "string",
"startTime": "datetime",
"endTime": "datetime",
"replicationType": "string",
"status": "string",
"source": "string",
"details": "string",
"tablesSuccessful": "integer",
"tablesFailed": "integer",
"tablesRemaining": "integer"
}

See Also
GET cloudMigrationStatus
Get cloudMigrationStatus
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a cloud migration status object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

GET businesscentralPrefix/companies({id})/cloudMigrationStatus({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a cloudMigrationStatus object in the response
body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v1.0/companies({id})/cloudMigrationStatus({id})

Response
Here is an example of the response.
{
"id" : "",
"runId" : "",
"startTime" : "",
"endTime" : "",
"replicationType" : "",
"status" : "",
"source" : "",
"details" : "",
"tablesSuccessful" : "",
"tablesFailed" : "",
"tablesRemaining" : ""
}

See Also
Tips for working with the APIs
cloudMigrationStatus
cloudMigrationStatusDetail resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents a cloud migration status detail in Business Central that is giving more information about the status
of the table that is under cloud migration.

NOTE
For information about enabling APIs for Business Central see guideline.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET cloudMigrationStatusDetail cloudMigrationStatusDetail Gets a cloud migration status detail


object.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

cloudMigrationStatus cloudMigrationStatus Gets the cloudmigrationstatus of the


cloudMigrationStatusDetail.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID Specifies the unique ID of the cloud


migration status detail. Non-editable.

runId string Specifies the unique ID of the runID.


You can use this value to filter the
details.

companyName string Specifies the company name that owns


the table that is cloud migrated.

tableName string Specifies the name of the table that is


cloud migrated.

status string Specifies the status of the table.


Possible values are: 'Failed, In Progress,
Successful, Warning, Not Started'.

recordsCopied integer Specifies the number of records that


were copied for this table.
P RO P ERT Y TYPE DESC RIP T IO N

totalRecords integer Specifies the total number of records in


the source table.

errors string Specifies any errors that occurred


during the replication.

estimatedSize decimal Read-Only property representing the


approximate size of the On-Prem
company. The data migrated will be
smaller, since the data will be
compressed and not all tables will be
included.

created boolean Specifies if the company was created. It


will not reflect if the setup of the
company was correct or not. For this
you should check the status property.
If the company has been created,
however status is different.

JSON representation
Here is a JSON representation of the cloudMigrationStatusDetail resource.

{
"id": "GUID",
"runId": "string",
"companyName": "string",
"tableName": "string",
"status": "string",
"recordsCopied": "integer",
"totalRecords": "integer",
"errors": "string"
}

See Also
GET cloudMigrationStatusDetail
Get cloudMigrationStatusDetails
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a cloud migration status detail object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

GET businesscentralPrefix/companies({id})/cloudMigrationStatusDetails({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a cloudMigrationStatusDetail object in the
response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v1.0/companies({id})/cloudMigrationStatusDetails({id})

Response
Here is an example of the response.

{
"id" : "",
"runId" : "",
"companyName" : "",
"tableName" : "",
"status" : "",
"recordsCopied" : "",
"totalRecords" : "",
"errors" : ""
}
See Also
Tips for working with the APIs
cloudMigrationStatusDetail
company resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents a company in Business Central.

NOTE
For information about enabling APIs for Business Central see guideline.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET company company Gets a company object.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

cloudMigrationCompanies cloudMigrationCompanies Gets the cloudmigrationcompanies of


the company.

cloudMigrationStatus cloudMigrationStatus Gets the cloudmigrationstatus of the


company.

cloudMigrationStatusDetails cloudMigrationStatusDetails Gets the cloudmigrationstatusdetails


of the company.

tableMappings tableMappings Gets the tablemappings of the


company.

setupCloudMigration setupCloudMigration Gets the setupcloudmigration of the


company.

sourceProductTypes sourceProductTypes Gets the sourceproducttypes of the


company.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the company. Non-


editable.

systemVersion string Specifies the internal version of the


company.

name string Represents the company's name.


P RO P ERT Y TYPE DESC RIP T IO N

displayName string Specifies the company's name. This


name will appear on all sales
documents for the company.

businessProfileId string Specifies the Business Profile ID linked


to the company.

systemCreatedAt datetime The datetime the company was


created.

systemCreatedBy GUID The ID of the user who created the


company.

systemModifiedAt datetime The last datetime the company was


modified.

systemModifiedBy GUID The ID of the user who last modified


the company.

estimatedSize decimal Read-Only property representing the


approximate size of the On-Prem
company. The data migrated will be
smaller, since the data will be
compressed and not all tables will be
included.

created boolean Specifies if the company was created. It


will not reflect if the setup of the
company was correct or not. For this
you should check the status property.
If the company has been created,
however status is different.

JSON representation
Here is a JSON representation of the company resource.

{
"id": "GUID",
"systemVersion": "string",
"name": "string",
"displayName": "string",
"businessProfileId": "string",
"systemCreatedAt": "datetime",
"systemCreatedBy": "GUID",
"systemModifiedAt": "datetime",
"systemModifiedBy": "GUID"
}

See Also
GET company
Get companies
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a company object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

GET businesscentralPrefix/companies({id})/companies({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a company object in the response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v1.0/companies({id})/companies({id})

Response
Here is an example of the response.

{
"id" : "",
"systemVersion" : "",
"name" : "",
"displayName" : "",
"businessProfileId" : "",
"systemCreatedAt" : "",
"systemCreatedBy" : "",
"systemModifiedAt" : "",
"systemModifiedBy" : ""
}
See Also
Tips for working with the APIs
company
setupCloudMigration resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents a setup cloud migration in Business Central.

NOTE
For information about enabling APIs for Business Central see guideline.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET setupCloudMigration setupCloudMigration Gets a setup cloud migration object.

POST setupCloudMigration setupCloudMigration Creates a setup cloud migration object.

PATCH setupCloudMigration setupCloudMigration Updates a setup cloud migration


object.

Bound Actions
The setupCloudMigration resource type offers a bound action called completeSetup which complete setups the
corresponding setupCloudMigration batch. This is illustrated in the following example:
COMPLETESETUP https://<server address>:<server API port>/<server instance
name>/api/v1.0/companies({id})/setupCloudMigrations({id})/Microsoft.NAV.completeSetup

The response has no content; the response code is 204.


The setupCloudMigration resource type offers a bound action called installedIntegrationRuntime which
installed integration runtimes the corresponding setupCloudMigration batch. This is illustrated in the following
example:
INSTALLEDINTEGRATIONRUNTIME https://<server address>:<server API port>/<server instance
name>/api/v1.0/companies({id})/setupCloudMigrations({id})/Microsoft.NAV.installedIntegrationRuntime

The response has no content; the response code is 204.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the setup cloud


migration. Non-editable.
P RO P ERT Y TYPE DESC RIP T IO N

productId string Specifies the source product for the


cloud migration. Available options can
be received from sourceProductTypes
API. Usually, values provided out of the
box are:
- DynamicsBCLast – use for cloud
migration with upgrade
- DynamicsBC – use for cloud
migration from the same version of
Dynamics Business Central
- DynamicsGP – use if you are setting
up Dynamics GP cloud migration.

sqlServerType string Specifies the SQL Server type. Values


can be:
- SQLServer – Use if you are migrating
from the database that is hosted on
the On-Prem SQL server
- AzureSQL – If you have uploaded the
database to migrate to Azure SQL
server.

sqlConnectionString string Specifies SQL connection string to the


OnPrem database that should be
cloud migrated

runtimeName string Represents a unique id of the Azure


Data Factory pipeline that will be used
to move the data. It is returned by the
first POST/PATCH request, this value is
not needed for AzureSQL database
type.

runtimeKey string Represents the key that is used to


connect the Microsoft Integration
Runtime to the Azure Data Factory. It
is returned by the first POST/PATCH
request, this value is not needed for
AzureSQL database type.

estimatedSize decimal Read-Only property representing the


approximate size of the On-Prem
company. The data migrated will be
smaller, since the data will be
compressed and not all tables will be
included.

created boolean Specifies if the company was created. It


will not reflect if the setup of the
company was correct or not. For this
you should check the status property.
If the company has been created,
however status is different.

JSON representation
Here is a JSON representation of the setupCloudMigration resource.
{
"id": "GUID",
"productId": "string",
"sqlServerType": "string",
"sqlConnectionString": "string",
"runtimeName": "string",
"runtimeKey": "string"
}

See Also
GET setupCloudMigration
POST setupCloudMigration
PATCH setupCloudMigration
Get setupCloudMigrations
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a setup cloud migration object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

GET businesscentralPrefix/companies({id})/setupCloudMigrations({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a setupCloudMigration object in the response
body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v1.0/companies({id})/setupCloudMigrations({id})

Response
Here is an example of the response.

{
"id" : "",
"productId" : "",
"sqlServerType" : "",
"sqlConnectionString" : "",
"runtimeName" : "",
"runtimeKey" : ""
}

See Also
Tips for working with the APIs
setupCloudMigration
POST setupCloudMigration
PATCH setupCloudMigration
Create setupCloudMigrations
2/6/2023 • 2 minutes to read • Edit Online

Creates a setup cloud migration in Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

POST businesscentralPrefix/companies({id})/setupCloudMigrations({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
setupCloudMigration , the setupCloudMigration will
not be updated.

Request body
In the request body, supply a JSON representation of a setupCloudMigration object.

Response
If successful, this method returns 201 Created response code and a setupCloudMigration object in the
response body.

Example
Request
Here is an example of the request.

POST https://{businesscentralPrefix}/api/v1.0/companies({id})/setupCloudMigrations({id})
Content-type: application/json
{
"id" : "",
"productId" : "",
"sqlServerType" : "",
"sqlConnectionString" : "",
"runtimeName" : "",
"runtimeKey" : ""
}

Response
Here is an example of the response.

HTTP/1.1 201 Created


Content-type: application/json
{
"id" : "",
"productId" : "",
"sqlServerType" : "",
"sqlConnectionString" : "",
"runtimeName" : "",
"runtimeKey" : ""
}

See Also
Tips for working with the APIs
setupCloudMigration
GET setupCloudMigration
PATCH setupCloudMigration
Update setupCloudMigrations
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of a setup cloud migration object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

PATCH businesscentralPrefix/companies({id})/setupCloudMigrations({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
setupCloudMigration , the setup cloud migration will
not be updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 200 OK response code and an updated setupCloudMigration object in the
response body.

Example
Request
Here is an example of the request.

PATCH https://{businesscentralPrefix}/api/v1.0/companies({id})/setupCloudMigrations({id})
Content-type: application/json
{
"id" : ,
"productId" :
}

Response
Here is an example of the response.

HTTP/1.1 200 OK
Content-type: application/json
{
"id" : ,
"productId" : ,
"sqlServerType" : ,
"sqlConnectionString" : ,
"runtimeName" : ,
"runtimeKey" :
}

See Also
Tips for working with the APIs
setupCloudMigration
GET setupCloudMigration
POST setupCloudMigration
sourceProductType resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents a source product type in Business Central that can be used for cloud migration. The values can be
used for setupCloudMigration to indicate from which source product to migrate from.

NOTE
For information about enabling APIs for Business Central see guideline.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET sourceProductType sourceProductType Gets a source product type object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id string The unique ID of the source product


type. Read-Only.

displayName string Specifies the source product type's


name. This name will appear on all
sales documents for the source
product type.

estimatedSize decimal Read-Only property representing the


approximate size of the On-Prem
company. The data migrated will be
smaller, since the data will be
compressed and not all tables will be
included.

created boolean Specifies if the company was created. It


will not reflect if the setup of the
company was correct or not. For this
you should check the status property.
If the company has been created,
however status is different.

JSON representation
Here is a JSON representation of the sourceProductType resource.

{
"id": "string",
"displayName": "string"
}
See Also
GET sourceProductType
Get sourceProductTypes
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a source product type object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

GET businesscentralPrefix/companies({id})/sourceProductTypes({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a sourceProductType object in the response
body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v1.0/companies({id})/sourceProductTypes({id})

Response
Here is an example of the response.

{
"id" : "",
"displayName" : ""
}

See Also
Tips for working with the APIs
sourceProductType
subscriptions resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents a subscriptions in Business Central.

NOTE
For information about enabling APIs for Business Central see guideline.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET subscriptions subscriptions Gets a subscriptions object.

DELETE subscriptions none Deletes a subscriptions object.

POST subscriptions subscriptions Creates a subscriptions object.

PATCH subscriptions subscriptions Updates a subscriptions object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

subscriptionId string Unique key for the subscription.

notificationUrl string URL to which webhook notifications


are sent.

resource string URL for the resource being subscribed


to. Supports relative and absolute URL.

userId GUID The ID of user that has created the


subscriptions.

lastModifiedDateTime datetime The last datetime the subscriptions


was modified. Read-Only.

clientState string Client state will be delivered with every


notification. This can be used as a
secret to verify message or for
managing state if needed.

expirationDateTime datetime Date and time for when the webhook


will expire.

systemCreatedAt datetime The datetime the company was


created.
P RO P ERT Y TYPE DESC RIP T IO N

systemCreatedBy GUID The ID of the user who created the


company.

systemModifiedAt datetime The last datetime the subscriptions


was modified.

systemModifiedBy GUID The ID of the user who last modified


the company.

estimatedSize decimal Read-Only property representing the


approximate size of the On-Prem
company. The data migrated will be
smaller, since the data will be
compressed and not all tables will be
included.

created boolean Specifies if the company was created. It


will not reflect if the setup of the
company was correct or not. For this
you should check the status property.
If the company has been created,
however status is different.

JSON representation
Here is a JSON representation of the subscriptions resource.

{
"subscriptionId": "string",
"notificationUrl": "string",
"resource": "string",
"userId": "GUID",
"lastModifiedDateTime": "datetime",
"clientState": "string",
"expirationDateTime": "datetime",
"systemCreatedAt": "datetime",
"systemCreatedBy": "GUID",
"systemModifiedAt": "datetime",
"systemModifiedBy": "GUID"
}

See Also
GET subscriptions
DELETE subscriptions
POST subscriptions
PATCH subscriptions
Get subscriptions
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a subscriptions object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

GET businesscentralPrefix/companies({id})/subscriptions({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a subscriptions object in the response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v1.0/companies({id})/subscriptions({id})

Response
Here is an example of the response.

{
"subscriptionId" : "",
"notificationUrl" : "",
"resource" : "",
"userId" : "",
"lastModifiedDateTime" : "",
"clientState" : "",
"expirationDateTime" : "",
"systemCreatedAt" : "",
"systemCreatedBy" : "",
"systemModifiedAt" : "",
"systemModifiedBy" : ""
}
See Also
Tips for working with the APIs
subscriptions
DELETE subscriptions
POST subscriptions
PATCH subscriptions
Delete subscriptions
2/6/2023 • 2 minutes to read • Edit Online

Deletes a subscriptions from Business Central.

HTTP request
Replaces the URL prefix for Business Central depending on environment following the guideline..

DELETE businesscentralPrefix/companies({id})/subscriptions({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
subscriptions , the subscriptions will not be updated.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns 204 No Content response code and deletes the subscriptions . It does not
return anything in the response body.

Example
Request
Here is an example of the request.

DELETE https://{businesscentralPrefix}/api/v1.0/companies({id})/subscriptions({id})

Response
Here is an example of the response.

HTTP/1.1 204 No Content

See Also
Tips for working with the APIs
subscriptions
GET subscriptions
POST subscriptions
PATCH subscriptions
Create subscriptions
2/6/2023 • 2 minutes to read • Edit Online

Creates a subscriptions in Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

POST businesscentralPrefix/companies({id})/subscriptions({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
subscriptions , the subscriptions will not be updated.

Request body
In the request body, supply a JSON representation of a subscriptions object.

Response
If successful, this method returns 201 Created response code and a subscriptions object in the response body.

Example
Request
Here is an example of the request.
POST https://{businesscentralPrefix}/api/v1.0/companies({id})/subscriptions({id})
Content-type: application/json
{
"subscriptionId" : "",
"notificationUrl" : "",
"resource" : "",
"userId" : "",
"lastModifiedDateTime" : "",
"clientState" : "",
"expirationDateTime" : "",
"systemCreatedAt" : "",
"systemCreatedBy" : "",
"systemModifiedAt" : "",
"systemModifiedBy" : ""
}

Response
Here is an example of the response.

HTTP/1.1 201 Created


Content-type: application/json
{
"subscriptionId" : "",
"notificationUrl" : "",
"resource" : "",
"userId" : "",
"lastModifiedDateTime" : "",
"clientState" : "",
"expirationDateTime" : "",
"systemCreatedAt" : "",
"systemCreatedBy" : "",
"systemModifiedAt" : "",
"systemModifiedBy" : ""
}

See Also
Tips for working with the APIs
subscriptions
GET subscriptions
DELETE subscriptions
PATCH subscriptions
Update subscriptions
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of a subscriptions object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

PATCH businesscentralPrefix/companies({id})/subscriptions({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
subscriptions , the subscriptions will not be updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 200 OK response code and an updated subscriptions object in the
response body.

Example
Request
Here is an example of the request.

PATCH https://{businesscentralPrefix}/api/v1.0/companies({id})/subscriptions({id})
Content-type: application/json
{
"subscriptionId" : ,
"notificationUrl" :
}

Response
Here is an example of the response.
HTTP/1.1 200 OK
Content-type: application/json
{
"subscriptionId" : ,
"notificationUrl" : ,
"resource" : ,
"userId" : ,
"lastModifiedDateTime" : ,
"clientState" : ,
"expirationDateTime" : ,
"systemCreatedAt" : ,
"systemCreatedBy" : ,
"systemModifiedAt" : ,
"systemModifiedBy" :
}

See Also
Tips for working with the APIs
subscriptions
GET subscriptions
DELETE subscriptions
POST subscriptions
tableMapping resource type
2/6/2023 • 2 minutes to read • Edit Online

Represents a table mapping in Business Central that can be used to include custom tables or tables that are not
included in the cloud migration out of the box. If you provide a table mapping the source table will be copied to
the destination table during cloud migration.

NOTE
For information about enabling APIs for Business Central see guideline.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET tableMapping tableMapping Gets a table mapping object.

DELETE tableMapping none Deletes a table mapping object.

POST tableMapping tableMapping Creates a table mapping object.

PATCH tableMapping tableMapping Updates a table mapping object.

Bound Actions
The tableMapping resource type offers a bound action called deleteAllForExtension which delete all for
extensions the corresponding tableMapping batch. This is illustrated in the following example:
DELETEALLFOREXTENSION https://<server address>:<server API port>/<server instance
name>/api/v1.0/companies({id})/tableMappings({id})/Microsoft.NAV.deleteAllForExtension

The response has no content; the response code is 204.


The tableMapping resource type offers a bound action called restoreDefaults which restore defaultss the
corresponding tableMapping batch. This is illustrated in the following example:
RESTOREDEFAULTS https://<server address>:<server API port>/<server instance
name>/api/v1.0/companies({id})/tableMappings({id})/Microsoft.NAV.restoreDefaults

The response has no content; the response code is 204.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the table mapping.


Non-editable.

tableId integer Specifies the destination table ID to be


mapped.

tableName string Specifies the destination table name.


P RO P ERT Y TYPE DESC RIP T IO N

sourceTableName string Specifies the source table name.

extensionName string Specifies the extension name that


owns the mapped table.

estimatedSize decimal Read-Only property representing the


approximate size of the On-Prem
company. The data migrated will be
smaller, since the data will be
compressed and not all tables will be
included.

created boolean Specifies if the company was created. It


will not reflect if the setup of the
company was correct or not. For this
you should check the status property.
If the company has been created,
however status is different.

JSON representation
Here is a JSON representation of the tableMapping resource.

{
"id": "GUID",
"tableId": "integer",
"tableName": "string",
"sourceTableName": "string",
"extensionName": "string"
}

See Also
GET tableMapping
DELETE tableMapping
POST tableMapping
PATCH tableMapping
Get tableMappings
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a table mapping object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

GET businesscentralPrefix/companies({id})/tableMappings({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a tableMapping object in the response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v1.0/companies({id})/tableMappings({id})

Response
Here is an example of the response.

{
"id" : "",
"tableId" : "",
"tableName" : "",
"sourceTableName" : "",
"extensionName" : ""
}

See Also
Tips for working with the APIs
tableMapping
DELETE tableMapping
POST tableMapping
PATCH tableMapping
Delete tableMappings
2/6/2023 • 2 minutes to read • Edit Online

Deletes a table mapping from Business Central.

HTTP request
Replaces the URL prefix for Business Central depending on environment following the guideline..

DELETE businesscentralPrefix/companies({id})/tableMappings({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
tableMapping , the tableMapping will not be updated.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns 204 No Content response code and deletes the tableMapping . It does not
return anything in the response body.

Example
Request
Here is an example of the request.

DELETE https://{businesscentralPrefix}/api/v1.0/companies({id})/tableMappings({id})

Response
Here is an example of the response.

HTTP/1.1 204 No Content

See Also
Tips for working with the APIs
tableMapping
GET tableMapping
POST tableMapping
PATCH tableMapping
Create tableMappings
2/6/2023 • 2 minutes to read • Edit Online

Creates a table mapping in Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

POST businesscentralPrefix/companies({id})/tableMappings({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
tableMapping , the tableMapping will not be updated.

Request body
In the request body, supply a JSON representation of a tableMapping object.

Response
If successful, this method returns 201 Created response code and a tableMapping object in the response body.

Example
Request
Here is an example of the request.

POST https://{businesscentralPrefix}/api/v1.0/companies({id})/tableMappings({id})
Content-type: application/json
{
"id" : "",
"tableId" : "",
"tableName" : "",
"sourceTableName" : "",
"extensionName" : ""
}

Response
Here is an example of the response.
HTTP/1.1 201 Created
Content-type: application/json
{
"id" : "",
"tableId" : "",
"tableName" : "",
"sourceTableName" : "",
"extensionName" : ""
}

See Also
Tips for working with the APIs
tableMapping
GET tableMapping
DELETE tableMapping
PATCH tableMapping
Update tableMappings
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of a table mapping object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline..

PATCH businesscentralPrefix/companies({id})/tableMappings({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
tableMapping , the table mapping will not be updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 200 OK response code and an updated tableMapping object in the
response body.

Example
Request
Here is an example of the request.

PATCH https://{businesscentralPrefix}/api/v1.0/companies({id})/tableMappings({id})
Content-type: application/json
{
"id" : ,
"tableId" :
}

Response
Here is an example of the response.
HTTP/1.1 200 OK
Content-type: application/json
{
"id" : ,
"tableId" : ,
"tableName" : ,
"sourceTableName" : ,
"extensionName" :
}

See Also
Tips for working with the APIs
tableMapping
GET tableMapping
DELETE tableMapping
POST tableMapping
accountingPeriod resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents an accounting period in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET accountingPeriod accountingPeriod Gets a accounting period object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the accounting


period. Non-editable.

displayName string Specifies the accounting period's name.


This name will appear on all sales
documents for the accounting period.

startingDate date

endingDate date

newFiscalYear boolean

fiscalYearStartDate date

fiscalYearEndDate date

closed boolean

lastModifiedDateTime datetime The last datetime the accounting


period was modified. Read-Only.

JSON representation
Here is a JSON representation of the accountingPeriod resource.
{
"id": "GUID",
"displayName": "string",
"startingDate": "date",
"endingDate": "date",
"newFiscalYear": "boolean",
"fiscalYearStartDate": "date",
"fiscalYearEndDate": "date",
"closed": "boolean",
"lastModifiedDateTime": "datetime"
}

See Also
GET accountingPeriod
Get accountingPeriods (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of an accounting period object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/accountingPeriods({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and an accountingPeriod object in the response
body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/accountingPeriods({id})

Response
Here is an example of the response.

{
"id" : "",
"displayName" : "",
"startingDate" : "",
"endingDate" : "",
"newFiscalYear" : "",
"fiscalYearStartDate" : "",
"fiscalYearEndDate" : "",
"closed" : "",
"lastModifiedDateTime" : ""
}
See Also
Tips for working with the APIs
accountingPeriod
businessUnit resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a business unit in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET businessUnit businessUnit Gets a business unit object.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

generalLedgerAccounts generalLedgerAccounts Gets the generalledgeraccounts of the


businessUnit.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the business unit.


Non-editable.

code string The code of the business unit.

startingDate date

endingDate date

lastModifiedDateTime datetime The last datetime the business unit


was modified. Read-Only.

JSON representation
Here is a JSON representation of the businessUnit resource.
{
"id": "GUID",
"code": "string",
"startingDate": "date",
"endingDate": "date",
"lastModifiedDateTime": "datetime"
}

See Also
GET businessUnit
Get businessUnits (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a business unit object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/businessUnits({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a businessUnit object in the response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/businessUnits({id})

Response
Here is an example of the response.

{
"id" : "",
"code" : "",
"startingDate" : "",
"endingDate" : "",
"lastModifiedDateTime" : ""
}

See Also
Tips for working with the APIs
businessUnit
company resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a company in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET company company Gets a company object.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

accountingPeriods accountingPeriods Gets the accountingperiods of the


company.

businessUnits businessUnits Gets the businessunits of the


company.

generalLedgerAccounts generalLedgerAccounts Gets the generalledgeraccounts of the


company.

dimensionValues dimensionValues Gets the dimensionvalues of the


company.

dimensionSetEntries dimensionSetEntries Gets the dimensionsetentries of the


company.

generalLedgerBudgets generalLedgerBudgets Gets the generalledgerbudgets of the


company.

customers customers Gets the customers of the company.

vendors vendors Gets the vendors of the company.

generalLedgerEntries generalLedgerEntries Gets the generalledgerentries of the


company.

detailedCustomerLedgerEntries detailedCustomerLedgerEntries Gets the


detailedcustomerledgerentries of the
company.
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

customerLedgerEntries customerLedgerEntries Gets the customerledgerentries of the


company.

vendorLedgerEntries vendorLedgerEntries Gets the vendorledgerentries of the


company.

detailedVendorLedgerEntries detailedVendorLedgerEntries Gets the detailedvendorledgerentries


of the company.

generalBudgetEntrys generalBudgetEntrys Gets the generalbudgetentrys of the


company.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the company. Non-


editable.

systemVersion string Specifies the internal version of the


company.

timestamp int64

name string Represents the company's name.

displayName string Specifies the company's name. This


name will appear on all sales
documents for the company.

businessProfileId string Specifies the Business Profile ID linked


to the company.

systemCreatedAt datetime The datetime the company was


created.

systemCreatedBy GUID The ID of the user who created the


company.

systemModifiedAt datetime The last datetime the company was


modified.

systemModifiedBy GUID The ID of the user who last modified


the company.

JSON representation
Here is a JSON representation of the company resource.
{
"id": "GUID",
"systemVersion": "string",
"timestamp": "int64",
"name": "string",
"displayName": "string",
"businessProfileId": "string",
"systemCreatedAt": "datetime",
"systemCreatedBy": "GUID",
"systemModifiedAt": "datetime",
"systemModifiedBy": "GUID"
}

See Also
GET company
Get companies (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a company object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/companies({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a company object in the response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/companies({id})

Response
Here is an example of the response.

{
"id" : "",
"systemVersion" : "",
"timestamp" : "",
"name" : "",
"displayName" : "",
"businessProfileId" : "",
"systemCreatedAt" : "",
"systemCreatedBy" : "",
"systemModifiedAt" : "",
"systemModifiedBy" : ""
}
See Also
Tips for working with the APIs
company
customer resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a customer in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET customer customer Gets a customer object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the customer. Non-


editable.

number string Specifies the number of the customer.

displayName string Specifies the customer's name. This


name will appear on all sales
documents for the customer.

type string

city string Specifies the customer's city.

state string Specifies the customer's state.

country string Specifies the customer's country.

postalCode string Specifies the customer's postal code.

salespersonCode string

balanceDue decimal Specifies total balance due.

creditLimit decimal

currencyCode string The default currency code for the


customer.
P RO P ERT Y TYPE DESC RIP T IO N

blocked string Specifies that transactions with the


customer cannot be posted. Set to All,
if the customer is blocked, set to blank
if not blocked.

lastModifiedDateTime datetime The last datetime the customer was


modified. Read-Only.

JSON representation
Here is a JSON representation of the customer resource.

{
"id": "GUID",
"number": "string",
"displayName": "string",
"type": "string",
"city": "string",
"state": "string",
"country": "string",
"postalCode": "string",
"salespersonCode": "string",
"balanceDue": "decimal",
"creditLimit": "decimal",
"currencyCode": "string",
"blocked": "string",
"lastModifiedDateTime": "datetime"
}

See Also
GET customer
Get customers (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a customer object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/customers({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a customer object in the response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/customers({id})

Response
Here is an example of the response.
{
"id" : "",
"number" : "",
"displayName" : "",
"type" : "",
"city" : "",
"state" : "",
"country" : "",
"postalCode" : "",
"salespersonCode" : "",
"balanceDue" : "",
"creditLimit" : "",
"currencyCode" : "",
"blocked" : "",
"lastModifiedDateTime" : ""
}

See Also
Tips for working with the APIs
customer
customerLedgerEntry resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a customer ledger entry in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET customerLedgerEntry customerLedgerEntry Gets a customer ledger entry object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

entryNumber integer G/L Entry number.

documentType string Specifies the document type of the


customer ledger entry.

description string Specifies the description of the


customer ledger entry.

postingDate date The date that the customer ledger


entry is posted.

documentNumber string Specifies a document number for the


customer ledger entry.

externalDocumentNumber string Specifies an external document


number for the customer ledger entry.

balancingAccountNumber string The balancing G/L Account number.

balancingAccountType string

customerNumber string The customer's number.

open boolean

dimensionSetID integer

currencyCode string The default currency code for the


customer ledger entry.
P RO P ERT Y TYPE DESC RIP T IO N

lastModifiedDateTime datetime The last datetime the customer ledger


entry was modified. Read-Only.

amount decimal Specifies the total amount (including


VAT) that the customer ledger entry
consists of.

debitAmount decimal Specifies the debitAmount of the


customer ledger entry.

creditAmount decimal Specifies the creditAmount of the


customer ledger entry.

amountLocalCurrency decimal

debitAmountLocalCurrency decimal

creditAmountLocalCurrency decimal

JSON representation
Here is a JSON representation of the customerLedgerEntry resource.

{
"entryNumber": "integer",
"documentType": "string",
"description": "string",
"postingDate": "date",
"documentNumber": "string",
"externalDocumentNumber": "string",
"balancingAccountNumber": "string",
"balancingAccountType": "string",
"customerNumber": "string",
"open": "boolean",
"dimensionSetID": "integer",
"currencyCode": "string",
"lastModifiedDateTime": "datetime",
"amount": "decimal",
"debitAmount": "decimal",
"creditAmount": "decimal",
"amountLocalCurrency": "decimal",
"debitAmountLocalCurrency": "decimal",
"creditAmountLocalCurrency": "decimal"
}

See Also
GET customerLedgerEntry
Get customerLedgerEntries (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a customer ledger entry object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/customerLedgerEntries({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a customerLedgerEntr y object in the response
body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/customerLedgerEntries({id})

Response
Here is an example of the response.
{
"entryNumber" : "",
"documentType" : "",
"description" : "",
"postingDate" : "",
"documentNumber" : "",
"externalDocumentNumber" : "",
"balancingAccountNumber" : "",
"balancingAccountType" : "",
"customerNumber" : "",
"open" : "",
"dimensionSetID" : "",
"currencyCode" : "",
"lastModifiedDateTime" : "",
"amount" : "",
"debitAmount" : "",
"creditAmount" : "",
"amountLocalCurrency" : "",
"debitAmountLocalCurrency" : "",
"creditAmountLocalCurrency" : ""
}

See Also
Tips for working with the APIs
customerLedgerEntry
detailedCustomerLedgerEntry resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a detailed customer ledger entry in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET detailedCustomerLedgerEntry detailedCustomerLedgerEntry Gets a detailed customer ledger entry


object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

entryNumber integer G/L Entry number.

entryType string

customerNumber string The customer's number.

amount decimal Specifies the total amount (including


VAT) that the detailed customer ledger
entry consists of.

debitAmount decimal Specifies the debitAmount of the


detailed customer ledger entry.

creditAmount decimal Specifies the creditAmount of the


detailed customer ledger entry.

amountLocalCurrency decimal

debitAmountLocalCurrency decimal

creditAmountLocalCurrency decimal

initialEntryGLobalDim1 string

initialEntryGLobalDim2 string

postingDate date The date that the detailed customer


ledger entry is posted.
P RO P ERT Y TYPE DESC RIP T IO N

currencyCode string The default currency code for the


detailed customer ledger entry.

lastModifiedDateTime datetime The last datetime the detailed


customer ledger entry was modified.
Read-Only.

JSON representation
Here is a JSON representation of the detailedCustomerLedgerEntry resource.

{
"entryNumber": "integer",
"entryType": "string",
"customerNumber": "string",
"amount": "decimal",
"debitAmount": "decimal",
"creditAmount": "decimal",
"amountLocalCurrency": "decimal",
"debitAmountLocalCurrency": "decimal",
"creditAmountLocalCurrency": "decimal",
"initialEntryGLobalDim1": "string",
"initialEntryGLobalDim2": "string",
"postingDate": "date",
"currencyCode": "string",
"lastModifiedDateTime": "datetime"
}

See Also
GET detailedCustomerLedgerEntry
Get detailedCustomerLedgerEntries (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a detailed customer ledger entry object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/detailedCustomerLedgerEntries({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a detailedCustomerLedgerEntr y object in the
response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/detailedCustomerLedgerEntries({id})

Response
Here is an example of the response.
{
"entryNumber" : "",
"entryType" : "",
"customerNumber" : "",
"amount" : "",
"debitAmount" : "",
"creditAmount" : "",
"amountLocalCurrency" : "",
"debitAmountLocalCurrency" : "",
"creditAmountLocalCurrency" : "",
"initialEntryGLobalDim1" : "",
"initialEntryGLobalDim2" : "",
"postingDate" : "",
"currencyCode" : "",
"lastModifiedDateTime" : ""
}

See Also
Tips for working with the APIs
detailedCustomerLedgerEntry
detailedVendorLedgerEntry resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a detailed vendor ledger entry in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET detailedVendorLedgerEntry detailedVendorLedgerEntry Gets a detailed vendor ledger entry


object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

entryNumber integer G/L Entry number.

entryType string

vendorNumber string Specifies vendor's number.

amount decimal Specifies the total amount (including


VAT) that the detailed vendor ledger
entry consists of.

debitAmount decimal Specifies the debitAmount of the


detailed vendor ledger entry.

creditAmount decimal Specifies the creditAmount of the


detailed vendor ledger entry.

amountLocalCurrency decimal

debitAmountLocalCurrency decimal

creditAmountLocalCurrency decimal

initialEntryGLobalDim1 string

initialEntryGLobalDim2 string

postingDate date The date that the detailed vendor


ledger entry is posted.
P RO P ERT Y TYPE DESC RIP T IO N

currencyCode string The default currency code for the


detailed vendor ledger entry.

lastModifiedDateTime datetime The last datetime the detailed vendor


ledger entry was modified. Read-Only.

JSON representation
Here is a JSON representation of the detailedVendorLedgerEntry resource.

{
"entryNumber": "integer",
"entryType": "string",
"vendorNumber": "string",
"amount": "decimal",
"debitAmount": "decimal",
"creditAmount": "decimal",
"amountLocalCurrency": "decimal",
"debitAmountLocalCurrency": "decimal",
"creditAmountLocalCurrency": "decimal",
"initialEntryGLobalDim1": "string",
"initialEntryGLobalDim2": "string",
"postingDate": "date",
"currencyCode": "string",
"lastModifiedDateTime": "datetime"
}

See Also
GET detailedVendorLedgerEntry
Get detailedVendorLedgerEntries (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a detailed vendor ledger entry object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/detailedVendorLedgerEntries({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a detailedVendorLedgerEntr y object in the
response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/detailedVendorLedgerEntries({id})

Response
Here is an example of the response.
{
"entryNumber" : "",
"entryType" : "",
"vendorNumber" : "",
"amount" : "",
"debitAmount" : "",
"creditAmount" : "",
"amountLocalCurrency" : "",
"debitAmountLocalCurrency" : "",
"creditAmountLocalCurrency" : "",
"initialEntryGLobalDim1" : "",
"initialEntryGLobalDim2" : "",
"postingDate" : "",
"currencyCode" : "",
"lastModifiedDateTime" : ""
}

See Also
Tips for working with the APIs
detailedVendorLedgerEntry
dimensionSetEntry resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a dimension set entry in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET dimensionSetEntry dimensionSetEntry Gets a dimension set entry object.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

dimensionValue dimensionValue Gets the dimensionvalue of the


dimensionSetEntry.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the dimension set


entry. Non-editable.

setId integer

dimensionCode string The dimension code.

dimensionDisplayName string

dimensionValueCode string The dimension value code.

dimensionValueDisplayName string

dimensionValueId integer

lastModifiedDateTime datetime The last datetime the dimension set


entry was modified. Read-Only.

JSON representation
Here is a JSON representation of the dimensionSetEntry resource.
{
"id": "GUID",
"setId": "integer",
"dimensionCode": "string",
"dimensionDisplayName": "string",
"dimensionValueCode": "string",
"dimensionValueDisplayName": "string",
"dimensionValueId": "integer",
"lastModifiedDateTime": "datetime"
}

See Also
GET dimensionSetEntry
Get dimensionSetEntries (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a dimension set entry object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/dimensionSetEntries({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a dimensionSetEntr y object in the response
body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/dimensionSetEntries({id})

Response
Here is an example of the response.

{
"id" : "",
"setId" : "",
"dimensionCode" : "",
"dimensionDisplayName" : "",
"dimensionValueCode" : "",
"dimensionValueDisplayName" : "",
"dimensionValueId" : "",
"lastModifiedDateTime" : ""
}
See Also
Tips for working with the APIs
dimensionSetEntry
dimensionValue resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a dimension value in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET dimensionValue dimensionValue Gets a dimension value object.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

dimensionSetEntries dimensionSetEntries Gets the dimensionsetentries of the


dimensionValue.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the dimension value.


Non-editable.

dimensionCode string The dimension code.

dimensionValueCode string The dimension value code.

dimensionValueName string

dimensionValueId integer

dimensionValueType string

blocked boolean Specifies that entries cannot be posted


to the dimension value. True indicates
account is blocked and posting is not
allowed.

indentation integer The dimension value item indentation


used in report layout.

consolidationCode string
P RO P ERT Y TYPE DESC RIP T IO N

globalDimensionNumber integer

lastModifiedDateTime datetime The last datetime the dimension value


was modified. Read-Only.

JSON representation
Here is a JSON representation of the dimensionValue resource.

{
"id": "GUID",
"dimensionCode": "string",
"dimensionValueCode": "string",
"dimensionValueName": "string",
"dimensionValueId": "integer",
"dimensionValueType": "string",
"blocked": "boolean",
"indentation": "integer",
"consolidationCode": "string",
"globalDimensionNumber": "integer",
"lastModifiedDateTime": "datetime"
}

See Also
GET dimensionValue
Get dimensionValues (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a dimension value object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/dimensionValues({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a dimensionValue object in the response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/dimensionValues({id})

Response
Here is an example of the response.

{
"id" : "",
"dimensionCode" : "",
"dimensionValueCode" : "",
"dimensionValueName" : "",
"dimensionValueId" : "",
"dimensionValueType" : "",
"blocked" : "",
"indentation" : "",
"consolidationCode" : "",
"globalDimensionNumber" : "",
"lastModifiedDateTime" : ""
}
See Also
Tips for working with the APIs
dimensionValue
generalBudgetEntry resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a general budget entry in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET generalBudgetEntry generalBudgetEntry Gets a general budget entry object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the general budget


entry. Non-editable.

number integer

description string Specifies the description of the general


budget entry.

budgetName string

businessUnitCode string

date date The date of the general budget entry.

accountNo string

amount decimal Specifies the total amount (including


VAT) that the general budget entry
consists of.

generalLedgerAccountNumber string

dimensionSetID integer

globalDimension1Code string

globalDimension2Code string

budgetDimension1Code string
P RO P ERT Y TYPE DESC RIP T IO N

budgetDimension2Code string

budgetDimension3Code string

budgetDimension4Code string

lastModifiedDateTime datetime The last datetime the general budget


entry was modified. Read-Only.

JSON representation
Here is a JSON representation of the generalBudgetEntry resource.

{
"id": "GUID",
"number": "integer",
"description": "string",
"budgetName": "string",
"businessUnitCode": "string",
"date": "date",
"accountNo": "string",
"amount": "decimal",
"generalLedgerAccountNumber": "string",
"dimensionSetID": "integer",
"globalDimension1Code": "string",
"globalDimension2Code": "string",
"budgetDimension1Code": "string",
"budgetDimension2Code": "string",
"budgetDimension3Code": "string",
"budgetDimension4Code": "string",
"lastModifiedDateTime": "datetime"
}

See Also
GET generalBudgetEntry
Get generalBudgetEntries (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a general budget entry object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/generalBudgetEntries({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a generalBudgetEntr y object in the response
body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/generalBudgetEntries({id})

Response
Here is an example of the response.
{
"id" : "",
"number" : "",
"description" : "",
"budgetName" : "",
"businessUnitCode" : "",
"date" : "",
"accountNo" : "",
"amount" : "",
"generalLedgerAccountNumber" : "",
"dimensionSetID" : "",
"globalDimension1Code" : "",
"globalDimension2Code" : "",
"budgetDimension1Code" : "",
"budgetDimension2Code" : "",
"budgetDimension3Code" : "",
"budgetDimension4Code" : "",
"lastModifiedDateTime" : ""
}

See Also
Tips for working with the APIs
generalBudgetEntry
generalLedgerAccount resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a general ledger account in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET generalLedgerAccount generalLedgerAccount Gets a general ledger account object.

Navigation
N AVIGAT IO N RET URN T Y P E DESC RIP T IO N

generalLedgerBudgets generalLedgerBudgets Gets the generalledgerbudgets of the


generalLedgerAccount.

businessUnit businessUnit Gets the businessunit of the


generalLedgerAccount.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the general ledger


account. Non-editable.

accountNumber string The number of the account that the


general ledger account is related to.

accountName string

accountType string The type of the account that the


general ledger account is related to.

accountCategory string

accountSubcategoryEntryNumber integer

accountSubcategoryDescription string

indentation integer The general ledger account item


indentation used in report layout.
P RO P ERT Y TYPE DESC RIP T IO N

netChange decimal The general ledger account net


change.

incomeBalance string

budgetFilter string

businessUnitFilter string

parentAccountNumber string

lastModifiedDateTime datetime The last datetime the general ledger


account was modified. Read-Only.

JSON representation
Here is a JSON representation of the generalLedgerAccount resource.

{
"id": "GUID",
"accountNumber": "string",
"accountName": "string",
"accountType": "string",
"accountCategory": "string",
"accountSubcategoryEntryNumber": "integer",
"accountSubcategoryDescription": "string",
"indentation": "integer",
"netChange": "decimal",
"incomeBalance": "string",
"budgetFilter": "string",
"businessUnitFilter": "string",
"parentAccountNumber": "string",
"lastModifiedDateTime": "datetime"
}

See Also
GET generalLedgerAccount
Get generalLedgerAccounts (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a general ledger account object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/generalLedgerAccounts({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a generalLedgerAccount object in the
response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/generalLedgerAccounts({id})

Response
Here is an example of the response.
{
"id" : "",
"accountNumber" : "",
"accountName" : "",
"accountType" : "",
"accountCategory" : "",
"accountSubcategoryEntryNumber" : "",
"accountSubcategoryDescription" : "",
"indentation" : "",
"netChange" : "",
"incomeBalance" : "",
"budgetFilter" : "",
"businessUnitFilter" : "",
"parentAccountNumber" : "",
"lastModifiedDateTime" : ""
}

See Also
Tips for working with the APIs
generalLedgerAccount
generalLedgerBudgets resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a general ledger budgets in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET generalLedgerBudgets generalLedgerBudgets Gets a general ledger budgets object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the general ledger


budgets. Non-editable.

displayName string Specifies the general ledger budgets's


name. This name will appear on all
sales documents for the general ledger
budgets.

description string Specifies the description of the general


ledger budgets.

blocked boolean Specifies that entries cannot be posted


to the general ledger budgets. True
indicates account is blocked and
posting is not allowed.

budgetDimension1Code string

budgetDimension2Code string

budgetDimension3Code string

budgetDimension4Code string

lastModifiedDateTime datetime The last datetime the general ledger


budgets was modified. Read-Only.

JSON representation
Here is a JSON representation of the generalLedgerBudgets resource.
{
"id": "GUID",
"displayName": "string",
"description": "string",
"blocked": "boolean",
"budgetDimension1Code": "string",
"budgetDimension2Code": "string",
"budgetDimension3Code": "string",
"budgetDimension4Code": "string",
"lastModifiedDateTime": "datetime"
}

See Also
GET generalLedgerBudgets
Get generalLedgerBudgets (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a general ledger budgets object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/generalLedgerBudgets({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a generalLedgerBudgets object in the
response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/generalLedgerBudgets({id})

Response
Here is an example of the response.

{
"id" : "",
"displayName" : "",
"description" : "",
"blocked" : "",
"budgetDimension1Code" : "",
"budgetDimension2Code" : "",
"budgetDimension3Code" : "",
"budgetDimension4Code" : "",
"lastModifiedDateTime" : ""
}
See Also
Tips for working with the APIs
generalLedgerBudgets
generalLedgerEntry resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a general ledger entry in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET generalLedgerEntry generalLedgerEntry Gets a general ledger entry object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the general ledger


entry. Non-editable.

number integer

description string Specifies the description of the general


ledger entry.

postingDate date The date that the general ledger entry


is posted.

accountNumber string The number of the account that the


general ledger entry is related to.

businessUnitCode string

reveresd boolean

documentNumber string Specifies a document number for the


general ledger entry.

externalDocumentNumber string Specifies an external document


number for the general ledger entry.

sourceType string

sourceNumber string

sourceCode string
P RO P ERT Y TYPE DESC RIP T IO N

amount decimal Specifies the total amount (including


VAT) that the general ledger entry
consists of.

debitAmount decimal Specifies the debitAmount of the


general ledger entry.

creditAmount decimal Specifies the creditAmount of the


general ledger entry.

vatAmount decimal

additionalCurrencyAmount decimal

dimensionSetID integer

globalDimension1Code string

globalDimension2Code string

lastModifiedDateTime datetime The last datetime the general ledger


entry was modified. Read-Only.

JSON representation
Here is a JSON representation of the generalLedgerEntry resource.

{
"id": "GUID",
"number": "integer",
"description": "string",
"postingDate": "date",
"accountNumber": "string",
"businessUnitCode": "string",
"reveresd": "boolean",
"documentNumber": "string",
"externalDocumentNumber": "string",
"sourceType": "string",
"sourceNumber": "string",
"sourceCode": "string",
"amount": "decimal",
"debitAmount": "decimal",
"creditAmount": "decimal",
"vatAmount": "decimal",
"additionalCurrencyAmount": "decimal",
"dimensionSetID": "integer",
"globalDimension1Code": "string",
"globalDimension2Code": "string",
"lastModifiedDateTime": "datetime"
}

See Also
GET generalLedgerEntry
Get generalLedgerEntries (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a general ledger entry object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/generalLedgerEntries({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a generalLedgerEntr y object in the response
body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/generalLedgerEntries({id})

Response
Here is an example of the response.
{
"id" : "",
"number" : "",
"description" : "",
"postingDate" : "",
"accountNumber" : "",
"businessUnitCode" : "",
"reveresd" : "",
"documentNumber" : "",
"externalDocumentNumber" : "",
"sourceType" : "",
"sourceNumber" : "",
"sourceCode" : "",
"amount" : "",
"debitAmount" : "",
"creditAmount" : "",
"vatAmount" : "",
"additionalCurrencyAmount" : "",
"dimensionSetID" : "",
"globalDimension1Code" : "",
"globalDimension2Code" : "",
"lastModifiedDateTime" : ""
}

See Also
Tips for working with the APIs
generalLedgerEntry
subscriptions resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a subscriptions in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET subscriptions subscriptions Gets a subscriptions object.

DELETE subscriptions none Deletes a subscriptions object.

POST subscriptions subscriptions Creates a subscriptions object.

PATCH subscriptions subscriptions Updates a subscriptions object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

subscriptionId string Unique key for the subscription.

notificationUrl string URL to which webhook notifications


are sent.

resource string URL for the resource being subscribed


to. Supports relative and absolute URL.

timestamp int64

userId GUID The ID of user that has created the


subscriptions.

lastModifiedDateTime datetime The last datetime the subscriptions


was modified. Read-Only.

clientState string Client state will be delivered with every


notification. This can be used as a
secret to verify message or for
managing state if needed.

expirationDateTime datetime Date and time for when the webhook


will expire.
P RO P ERT Y TYPE DESC RIP T IO N

systemCreatedAt datetime The datetime the company was


created.

systemCreatedBy GUID The ID of the user who created the


company.

systemModifiedAt datetime The last datetime the subscriptions


was modified.

systemModifiedBy GUID The ID of the user who last modified


the company.

JSON representation
Here is a JSON representation of the subscriptions resource.

{
"subscriptionId": "string",
"notificationUrl": "string",
"resource": "string",
"timestamp": "int64",
"userId": "GUID",
"lastModifiedDateTime": "datetime",
"clientState": "string",
"expirationDateTime": "datetime",
"systemCreatedAt": "datetime",
"systemCreatedBy": "GUID",
"systemModifiedAt": "datetime",
"systemModifiedBy": "GUID"
}

See Also
GET subscriptions DELETE subscriptions POST subscriptions PATCH subscriptions
Get subscriptions (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a subscriptions object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/subscriptions({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a subscriptions object in the response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/subscriptions({id})

Response
Here is an example of the response.
{
"subscriptionId" : "",
"notificationUrl" : "",
"resource" : "",
"timestamp" : "",
"userId" : "",
"lastModifiedDateTime" : "",
"clientState" : "",
"expirationDateTime" : "",
"systemCreatedAt" : "",
"systemCreatedBy" : "",
"systemModifiedAt" : "",
"systemModifiedBy" : ""
}

See Also
Tips for working with the APIs
subscriptions
DELETE subscriptions
POST subscriptions
PATCH subscriptions
Delete subscriptions (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Deletes a subscriptions from Business Central.

HTTP request
Replaces the URL prefix for Business Central depending on environment following the guideline.

DELETE businesscentralPrefix/companies({id})/subscriptions({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
subscriptions , the subscriptions will not be updated.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns 204 No Content response code and deletes the subscriptions . It does not
return anything in the response body.

Example
Request
Here is an example of the request.

DELETE https://{businesscentralPrefix}/api/v2.0/companies({id})/subscriptions({id})

Response
Here is an example of the response.

HTTP/1.1 204 No Content

See Also
Tips for working with the APIs
subscriptions
GET subscriptions
POST subscriptions
PATCH subscriptions
Create subscriptions (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Creates a subscriptions in Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

POST businesscentralPrefix/companies({id})/subscriptions({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
subscriptions , the subscriptions will not be updated.

Request body
In the request body, supply a JSON representation of a subscriptions object.

Response
If successful, this method returns 201 Created response code and a subscriptions object in the response body.

Example
Request
Here is an example of the request.
POST https://{businesscentralPrefix}/api/v2.0/companies({id})/subscriptions({id})
Content-type: application/json
{
"subscriptionId" : "",
"notificationUrl" : "",
"resource" : "",
"timestamp" : "",
"userId" : "",
"lastModifiedDateTime" : "",
"clientState" : "",
"expirationDateTime" : "",
"systemCreatedAt" : "",
"systemCreatedBy" : "",
"systemModifiedAt" : "",
"systemModifiedBy" : ""
}

Response
Here is an example of the response.

HTTP/1.1 201 Created


Content-type: application/json
{
"subscriptionId" : "",
"notificationUrl" : "",
"resource" : "",
"timestamp" : "",
"userId" : "",
"lastModifiedDateTime" : "",
"clientState" : "",
"expirationDateTime" : "",
"systemCreatedAt" : "",
"systemCreatedBy" : "",
"systemModifiedAt" : "",
"systemModifiedBy" : ""
}

See Also
Tips for working with the APIs
subscriptions
GET subscriptions
DELETE subscriptions
PATCH subscriptions
Update subscriptions (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Updates the properties of a subscriptions object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

PATCH businesscentralPrefix/companies({id})/subscriptions({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Content-Type application/json

If-Match Required. When this request header is included and the eTag
provided does not match the current tag on the
subscriptions , the subscriptions will not be updated.

Request body
In the request body, supply the values for relevant fields that should be updated. Existing properties that are not
included in the request body will maintain their previous values or be recalculated based on changes to other
property values. For best performance you shouldn't include existing values that haven't changed.

Response
If successful, this method returns a 200 OK response code and an updated subscriptions object in the
response body.

Example
Request
Here is an example of the request.

PATCH https://{businesscentralPrefix}/api/v2.0/companies({id})/subscriptions({id})
Content-type: application/json
{
"subscriptionId" : ,
"notificationUrl" :
}

Response
Here is an example of the response.
HTTP/1.1 200 OK
Content-type: application/json
{
"subscriptionId" : ,
"notificationUrl" : ,
"resource" : ,
"timestamp" : ,
"userId" : ,
"lastModifiedDateTime" : ,
"clientState" : ,
"expirationDateTime" : ,
"systemCreatedAt" : ,
"systemCreatedBy" : ,
"systemModifiedAt" : ,
"systemModifiedBy" :
}

See Also
Tips for working with the APIs
subscriptions
GET subscriptions
DELETE subscriptions
POST subscriptions
vendor resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a vendor in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET vendor vendor Gets a vendor object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

id GUID The unique ID of the vendor. Non-


editable.

number string Specifies the number of the vendor.

displayName string Specifies the vendor's name. This name


will appear on all sales documents for
the vendor.

city string Specifies the vendor's city.

state string Specifies the vendor's state.

country string Specifies the vendor's country.

postalCode string Specifies the vendor's postal code.

currencyCode string The default currency code for the


vendor.

paymentTermsId GUID Specifies which payment term the


vendor uses.

paymentMethodId GUID Specifies which payment method the


vendor uses.

taxLiable boolean Specifies if the vendor or vendor is


liable for sales tax. Set to true if the
vendor is tax liable.
P RO P ERT Y TYPE DESC RIP T IO N

blocked string Specifies that transactions with the


vendor cannot be posted. Set to All, if
the vendor is blocked, set to blank if
not blocked.

balance decimal Specifies vendor's total balance.

lastModifiedDateTime datetime The last datetime the vendor was


modified. Read-Only.

JSON representation
Here is a JSON representation of the vendor resource.

{
"id": "GUID",
"number": "string",
"displayName": "string",
"city": "string",
"state": "string",
"country": "string",
"postalCode": "string",
"currencyCode": "string",
"paymentTermsId": "GUID",
"paymentMethodId": "GUID",
"taxLiable": "boolean",
"blocked": "string",
"balance": "decimal",
"lastModifiedDateTime": "datetime"
}

See Also
GET vendor
Get vendors (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a vendor object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/vendors({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a vendor object in the response body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/vendors({id})

Response
Here is an example of the response.
{
"id" : "",
"number" : "",
"displayName" : "",
"city" : "",
"state" : "",
"country" : "",
"postalCode" : "",
"currencyCode" : "",
"paymentTermsId" : "",
"paymentMethodId" : "",
"taxLiable" : "",
"blocked" : "",
"balance" : "",
"lastModifiedDateTime" : ""
}

See Also
Tips for working with the APIs
vendor
vendorLedgerEntry resource type (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Represents a vendor ledger entry in Business Central.

NOTE
For information about enabling APIs for Business Central see Enabling the APIs for Dynamics 365 Business Central.

Methods
M ET H O D RET URN T Y P E DESC RIP T IO N

GET vendorLedgerEntry vendorLedgerEntry Gets a vendor ledger entry object.

Properties
P RO P ERT Y TYPE DESC RIP T IO N

entryNumber integer G/L Entry number.

documentType string Specifies the document type of the


vendor ledger entry.

description string Specifies the description of the vendor


ledger entry.

postingDate date The date that the vendor ledger entry


is posted.

documentNumber string Specifies a document number for the


vendor ledger entry.

externalDocumentNumber string Specifies an external document


number for the vendor ledger entry.

balancingAccountNumber string The balancing G/L Account number.

balancingAccountType string

vendorNumber string Specifies vendor's number.

open boolean

dimensionSetID integer

currencyCode string The default currency code for the


vendor ledger entry.
P RO P ERT Y TYPE DESC RIP T IO N

lastModifiedDateTime datetime The last datetime the vendor ledger


entry was modified. Read-Only.

amount decimal Specifies the total amount (including


VAT) that the vendor ledger entry
consists of.

debitAmount decimal Specifies the debitAmount of the


vendor ledger entry.

creditAmount decimal Specifies the creditAmount of the


vendor ledger entry.

amountLocalCurrency decimal

debitAmountLocalCurrency decimal

creditAmountLocalCurrency decimal

JSON representation
Here is a JSON representation of the vendorLedgerEntry resource.

{
"entryNumber": "integer",
"documentType": "string",
"description": "string",
"postingDate": "date",
"documentNumber": "string",
"externalDocumentNumber": "string",
"balancingAccountNumber": "string",
"balancingAccountType": "string",
"vendorNumber": "string",
"open": "boolean",
"dimensionSetID": "integer",
"currencyCode": "string",
"lastModifiedDateTime": "datetime",
"amount": "decimal",
"debitAmount": "decimal",
"creditAmount": "decimal",
"amountLocalCurrency": "decimal",
"debitAmountLocalCurrency": "decimal",
"creditAmountLocalCurrency": "decimal"
}

See Also
GET vendorLedgerEntry
Get vendorLedgerEntries (Beta)
2/6/2023 • 2 minutes to read • Edit Online

Retrieves the properties and relationships of a vendor ledger entry object for Business Central.

HTTP request
Replace the URL prefix for Business Central depending on environment following the guideline.

GET businesscentralPrefix/companies({id})/vendorLedgerEntries({id})

Request headers
H EA DER VA L UE

Authorization Bearer {token}. Required.

Request body
Do not supply a request body for this method.

Response
If successful, this method returns a 200 OK response code and a vendorLedgerEntr y object in the response
body.

Example
Request
Here is an example of the request.

GET https://{businesscentralPrefix}/api/v2.0/companies({id})/vendorLedgerEntries({id})

Response
Here is an example of the response.
{
"entryNumber" : "",
"documentType" : "",
"description" : "",
"postingDate" : "",
"documentNumber" : "",
"externalDocumentNumber" : "",
"balancingAccountNumber" : "",
"balancingAccountType" : "",
"vendorNumber" : "",
"open" : "",
"dimensionSetID" : "",
"currencyCode" : "",
"lastModifiedDateTime" : "",
"amount" : "",
"debitAmount" : "",
"creditAmount" : "",
"amountLocalCurrency" : "",
"debitAmountLocalCurrency" : "",
"creditAmountLocalCurrency" : ""
}

See Also
Tips for working with the APIs
vendorLedgerEntry
Migrate On-Premises Data to Business Central
Online
2/6/2023 • 24 minutes to read • Edit Online

Organizations that run their workloads on-premises but are looking to move to the cloud can easily migrate to
Business Central online. By moving to the cloud, users get the benefits of cloud scenarios such as Machine
Learning, Power BI, Power Automate, and others to drive suggested actions.
If you're not already familiar with Business Central online, take a look here.

Supported migration paths


You can use the built-in migration tools to migrate data to Business Central online from specific product
versions. The on-premises solution must use SQL Server 2016 or a later version, and the database must have
compatibility level 130 or higher. Currently, you can migrate to Business Central online from the following
products:
Dynamics GP 2015 and later versions
Business Central on-premises
Currently, you can migrate to Business Central online from the earlier versions 14 through 20. For an
indication of compatibility across minor versions, see here. You can also switch to online from the current
version (21).

TIP
If you are currently on a version of Dynamics NAV, you must upgrade to Business Central on-premises, and then switch to
Business Central online. For more information, see Upgrading from Dynamics NAV to Business Central online.

If a customer is coming from another product, you can use configuration packages and templates to migrate
their data to Business Central on-premises, and then use the cloud migration tool to switch to Business Central
online. For more information, see Set Up Company Configuration Packages.

TIP
Customers coming from QuickBooks can use apps from Microsoft to move to Business Central online. For more
information, see Changing from a QuickBooks App to Dynamics 365 Business Central.

Prerequisites
The customer must have a Business Central online tenant
The person who runs the migration must be signed in as an administrator of the Microsoft 365 tenant
and Business Central online
The on-premises solution must be on the list of supported migration paths
If the solution is based on an older version of the on-premises product, upgrade to the latest
supported version
The on-premises database must be ready
The on-premises solution must use SQL Server 2016 SP1 or later
The database must have compatibility level 130 or higher
Update statistics and reorganize indexes on all tables on the source database
This will ensure that the migration runs as fast as possible. For more information, see the
documentation for sp_updatestats (Transact-SQL) and Resolve index fragmentation by
reorganizing or rebuilding indexes.
At least one user has SUPER permissions in the target company in Business Central online.
This is the only user who can make changes in Business Central online. All users that don't have SUPER
permissions will be automatically reassigned to the intelligent cloud user group. This will limit them to
read-only access to data in Business Central online. For more information, se the Business Central
permission sets section.
Consider reducing the amount of data that you migrate.
You can migrate the data that you want to take with you to the cloud. If you need more storage than the
default 80 GB, you can buy additional environments or additional storage capacity. We recommend that
you consider reducing the amount of data that you migrate so that it is less than 30 GB in each migration
run. For example, reduce the number of companies that you are migrating data for, or delete outdated
data in tables that contain log entries and archived records. Also, review how you can manage database
capacity in a Business Central online environment.
You can specify which companies to include in the migration in the assisted setup guide, and you can
view the migration status of each company in the Cloud Migration Management page.
If you want to add more companies after the first selection of companies, you can add more companies in
the Cloud Migration Management page in Business Central online. For more information, see Run the
tool multiple times. But use the Capacity section of the Business Central administration center to keep
track of how much data you migrate.

TIP
On page 9035 Data Administration , you can find reports that are used to compress or cleanup the data. In
earlier Business Central versions, the page may not be present. However, most reports can be found using Search
.

In certain cases, the customer wants to migrate large amounts of data. For large source databases, we
recommend deploying the source database to an Azure SQL Database, and then setting up cloud
migration from Azure SQL source instead of the on-premise SQL Server. This eliminates the need to
install and maintain self-hosted integration runtime on-premise, and ensures much faster data
replication.
Deploying to Azure SQL can be an easy and quick process if done in SQL Server Management Studio
connected to the on-premise database. Follow the Deploy Database to Microsoft Azure SQL
Database wizard, which you find in the Tasks context menu on the database. When prompted to choose
a service tier for the new Azure SQL database, remember that the lowest configurations may not be
adequate for migrating large amounts of data. Consider the right balance between performance and
price that would be preferable in your case. The database service tier can be tuned later in Azure Portal.
We continually work on improving and optimizing the migration tool for larger database sizes. For
example, customers can buy more environments, and they can buy extra storage. For more information,
see Managing Capacity. If more assistance is required, contact support as described in Escalating support
issues to Microsoft.
There are no firm limits on the size of the database, the number of daily transactions, or the number of
users that can migrate from on-premises to Business Central online.
To help you test the migration, you can migrate data to the target production environment, and then
create a sandbox environment based on this production environment. For Business Central on-premises,
first use the data replication step in the production environment, and then run the data upgrade step in
the sandbox environment for safe testing before you run the data upgrade step in the production
environment.

IMPORTANT
Only run the data migration into a single environment. Don't reuse the same on-premises database for multiple
data migrations—restore a fresh backup of the database. You have the option of migrating to a sandbox, copying
to another sandbox, and testing upgrade there. If successful, you can then copy the upgraded sandbox to the
production environment and delete all other environments.

Plan the switch to use Business Central online for production carefully to not start until migration is
complete

IMPORTANT
Do not set up cloud migration for a production environment that is already in use for business. You risk that the
migration process overwrites data that is needed to run the business. Even if your migration targets a different
company in that environment, you risk that the upgrade overwrites data that is shared across companies in the
target environment.

Schedule the migration to not conflict with an update of Business Central online
If you set up cloud migration for an environment, the environment cannot be upgraded. If you want to
upgrade the environment, you must disable cloud migration. If you want to move more companies, set
up cloud migration again once the upgrade is complete. By separating upgrade from cloud migration, we
remove the risk of potentially corrupting data if the upgrade touches tables with records in both migrated
and non-migrated companies. Upgrade the target environment first, then migrate.
Install the migration apps in Business Central
In the Business Central administration center, open the environment that you intend to migrate your data
to, and then choose the Apps action. Make sure that these apps have the latest updates installed:
Intelligent Cloud Base
Business Central Intelligent Cloud

IMPORTANT
In Business Central online, install, publish, or upgrade the Intelligent Cloud Base extension first, and then the
product-specific extension or extensions.

If you're migrating from an earlier supported version of Business Central, you must also make sure that
the following apps are updated:
Business Central Cloud Migration – Previous Release
Business Central Cloud Migration – Previous Release [code for your country-specific version]
Also, at the end of the upgrade, you must make sure that the applicationVersion field in the
ndo$tenantdatabaseproperty table is set to the right version. If the field is blank, or if it's set to an older
version than the migration tool supports, the migration can't run. For more information, see Post-
upgrade tasks.
If you're migrating from Dynamics GP, make sure that the following apps are installed and updated:
Dynamics GP Intelligent Cloud
Dynamics GP History SmartLists

IMPORTANT
Migrating from Dynamics GP using the Cloud Migration Setup assisted setup guide is currently only
supported for the following markets:
United States
Canada
United Kingdom
Australia

If you want to migrate from another product, check the marketplace for an app to help.
Test extensions
It's highly recommended that you test the impact of any extension in a sandbox environment before
having it installed in your production environment in Business Central online to help avoid any data
failures or untended consequences.

End-to-end process
You manage cloud migration from Business Central online. But the on-premises solution remains the operative
environment until you complete the migration. Do not set up cloud migration for a production environment that
is already in use for business. You risk that the migration process overwrites data that is needed to run the
business. Even if your migration targets a different company in that environment, you risk that the upgrade
overwrites data that is shared across companies in the target environment.
Any existing data in Business Central online will be overwritten with data from your on-premises solution, or
source, once the data migration process is run.
If you don't want data in Business Central online to be overwritten, don't configure the connection. The only
exception is when you migrate from Business Central on-premises current version because you can run the
migration tool multiple times in that specific scenario.
If your data source is Business Central on-premises, several stored procedures will be added to the SQL Server
instance that you define. These stored procedures are required to migrate data from your SQL Server database
to the Azure SQL server associated with your Business Central tenant.
The main steps in a migration process are:
1. Have a target environment with a paid subscription
2. Determine which data to migrate
For Business Central on-premises, determine which companies to migrate and the number of
migration runs to use to migrate the required data
For Dynamics GP, you can use the migration process to move historical data to Azure Data Lake
For Dynamics NAV, upgrade to Business Central on-premises first, and then migrate
3. Migrate data, using the Cloud Migration Setup assisted setup guide in Business Central online
4. Test the result of the migration
5. Set up users, permissions, and other configurations in Business Central online
6. Stop using the on-premises solution, switch off the migration, and tell users to start using Business
Central online for daily business

TIP
Meanwhile, users can train themselves in how to work in Business Central using a sandbox environment and the free
training modules on Microsoft Learn.

Migrate data
Data migration is the process of securely migrating data from an on-premises SQL Server instance (or Azure
SQL) to Business Central online. The process uses the Azure Data Factory (ADF) to migrate the data between
databases directly, meaning it doesn't look at any permissions within the applications you're transferring data
between, only SQL permissions.
Data is migrated table by table, and success and failures are tracked for each table. If a table fails to migrate, the
error will be captured, and the migration moves on to the next table until completed. Tables will fail to migrate if
they can't be found, or if the schema doesn't match between the cloud and the on-premises tables.
The initial data migration time can vary depending on factors such as the amount of data to migrate, your SQL
Server configuration, and your connection speeds. The initial migration will take the longest amount of time to
complete because all data is migrating. After the initial migration, only changes in data will be migrated, so each
iteration runs more quickly. You don't need to run the migration process more than once if you don't want to.
However, if you're running the migration while users are still using the on-premises system, you must run at
least one more migration in order to ensure all data was moved to the cloud before you start transacting in
Business Central online.

IMPORTANT
Do not set up cloud migration for a production environment that is already in use for business. You risk that the
migration process overwrites data that is needed to run the business. Even if your migration targets a different company
in that environment, you risk that the upgrade overwrites data that is shared across companies in the target
environment.

Run the assisted setup guide


To migrate data, in the target company in Business Central online, run the Cloud Migration Setup assisted
setup guide.

IMPORTANT
You must be signed in as an administrator of the Microsoft 365 tenant as well as Business Central online.

If the user running this flow is a delegated administrator, they must receive approval from a licensed user with
either the Essentials or the Premium license and SUPER permissions in order to run the cloud migration. In this
case, the Data Migration Setup guide will display an extra step, where the delegated administrator can copy
the auto-generated approval link and send it to the licensed user for approval. Once the licensed user has
approved the request, the delegated administrator can continue with the setup of the cloud migration and
perform all other steps required to complete that process. The licensed user can always revoke the permission
to run the migration by choosing the same approval link that was shared by the delegated administrator, or
from the Cloud Migration Approval page.

TIP
We recommend that you start the migration by running the assisted setup from a company other than the company that
you are migrating data to. For example, sign into the demonstration company, CRONUS, and start the process there. This
way, you can make sure that all users are logged out of the original company and the target company. This is especially
important when you migrate from Business Central on-premises current version because you can run the migration tool
multiple times.

IMPORTANT
Do not set up cloud migration for a production environment that is already in use for business. You risk that the
migration process overwrites data that is needed to run the business. Even if your migration targets a different company
in that environment, you risk that the upgrade overwrites data that is shared across companies in the target
environment.

Once the setup guide is complete and data migration is activated, the initial data migration ready to be run from
the Cloud Migration Management page whenever you want. Go to Manage the Migration.

TIP
You can migrate the data that you want to take with you to the cloud. If you need more storage than the default 80 GB,
you can buy additional environments or additional storage capacity. We recommend that you consider reducing the
amount of data that you migrate so that it is less than 30 GB in each migration run. For example, reduce the number of
companies that you are migrating data for, or delete outdated data in tables that contain log entries and archived records.
Also, review how you can manage database capacity in a Business Central online environment.

Specify the SQL connection


If the product you selected requires a SQL connection, this page will be presented. Other source applications
may require different information to connect to them. This page will display the connection information based
on the product that you specified in the previous page. This is defined from the installed extensions for the
product you've selected. The following list provides more details about the fields in this part of the assisted
setup guide.
SQL Connection
Specify SQL Server for a locally installed SQL Server instance, or Azure SQL.

IMPORTANT
Azure SQL Managed Instance is not supported.

SQL Connection string


You must specify the connection string to your SQL Server, including the name of the server that SQL
Server is running on, and the name of the instance, the database, and the relevant user account.
For example, Server=MyServer\BCDEMO;Database=BC180;UID=MySQLAccount;PWD=MyPassWord; , if you're migrating
from Business Central on-premises, version 18. For more information, see the SQL Server blog.
The following snippets illustrate a couple of connection strings with different formats:
Server={Server Name\Instance Name};Initial Catalog={Database Name};UserID={SQL Authenticated
UserName};Password={SQL Authenticated Password};

Server={Server Name\Instance Name};Database={Database Name};User Id={SQL Server Authenticated


UserName};Password={SQL Server Authenticated Password};

IMPORTANT
In the second connection string format, don't forget to add the space in User Id parameter as it's mandatory and
can throw an error if it's missing.

The SQL connection string is passed to Azure Data Factory (ADF), where it's encrypted and delivered to
your Self-Hosted Integration Runtime and used to communicate with your SQL Server instance during
the data migration process.
Integration runtime name
If your SQL connection is SQL Server, you must specify the runtime service that will be used to replicate
the data from the defined source to Business Central online. The integration runtime must be running on
the machine that holds the SQL Server database. If you don't already have a runtime service, leave the
field empty, and then choose the Next button.
If you leave the Integration runtime name field empty, a new page appears from where you can
download the self-hosted integration runtime that you must install. Follow the instructions on the page.
Hover over a field to read a short description.
Once you choose Next , a new pipeline will be created in the Azure service. This takes less than a minute to
complete, in most cases. If you want to test your SQL string, open the Microsoft Integration Runtime
Configuration Manager , and then choose the Diagnostics menu option. From there, you can test to see if
the connection is good.

Manage the migration


Once you have set up this configuration, you can manage your cloud environment and data migration from the
Cloud Migration Management page in Business Central online.
The Cloud Migration Management page provides information about your data migration runs and the ability
to manage your migration services, for example.
The page provides a view of the status of all migration runs. You can view the time the migration ran and the
status of each migration. The Migration Information tiles show the number of migrated tables and the
number of tables that didn't migrate due to warnings or errors. Choose a tile to drill into more details and
guidance to correct any errors.
There's also a tile that shows tables that aren't migrated due to problems with the data. For example, tables with
permissions aren't migrated from on-premises solutions because permissions work differently between online
and on-premises.
The following table describes the actions that you can run from the page:

A C T IO N DESC RIP T IO N
A C T IO N DESC RIP T IO N

Run Migration Now Choose this action to start the data migration manually. The
migration can also be used for subsequent runs after the
initial migration. On subsequent runs, the migration tool will
only migrate changes that have happened since the previous
migration was run. Change tracking is used to identify what
data should be moved in those subsequent runs. However,
the migration tool can't run if the target environment is
being upgraded. In that case, you must disable cloud
migration, upgrade, and then set up cloud migration again.

Run Data Upgrade Now Choose this action to upgrade data, such as if you're
migrating data from an earlier version to the latest version
of Business Central.

Refresh Status If a migration run is in progress, you can choose to refresh


status to update the page. If the run is complete, the status
will update using the refresh status action without having to
close the window and reopen it.

Reset Cloud Data You may run into instances where you need to reset your
cloud data. This option will clear all data in your cloud tenant
and enable you to start over with data migration. Only run
this process if you want to start the migration process all
over from the beginning. If you need to clear data in your
cloud tenant, and you have connectivity issues that persist
for more than 7 days, you must contact customer support.
They'll create a ticket to have your tenant data cleared. Only
run this process if you want to start the data migration all
over and bring all data from on-premises to your cloud
tenant.

Get Runtime Service Key Returns the existing runtime key.

Reset Runtime Service Key If at any time you suspect that your Self-Hosted Integration
Runtime key is no longer secure, you can choose this option
to regenerate a new key. A new key will be generated for
you and automatically be updated in the Self-Host
Integration Runtime service.

Disable Cloud Migration Opens a guide that helps you through a checklist of
instructions to disable the cloud migration configuration.
Use the guide when you've migrated the data that you want
to migrate, or when you want to upgrade the target
environment. Once the steps in this process are complete,
you can use your Business Central online tenant as your
primary solution, or you can upgrade the environment.

Check for Update If there have been changes to the migration service, we'll
publish the new service. This action will check to see if a new
service has been published. The check will display the version
of the service you're currently running and then also display
the latest service published. Then, you can choose to update
your solution. We recommend that you update the solution
if a newer version has been published.
A C T IO N DESC RIP T IO N

Select Companies to Migrate If your database contains more than one company, use this
action to specify which company or companies to run a
migration for. For example, you're migrating a large database
with multiple companies, so you break down the migration
in several runs by including one or a few companies in each
migration run. You can see the estimated size of each
company

Define User Mappings This option is available when you sign in to a particular
company that has been migrated. This action should be
done in one of the companies you've migrated. This action
gives you a list of the users that were in your on-premises
environment, and then gives you a list of your Microsoft 365
users, so that you can map the two together. This process
renames the Name field on the User Card to match the
user name in your on-premises solution. It isn't a required
step, but if you use some of the processes in Business
Central that work with the user name, such as time sheets,
you may want to map users. Time sheets are visible based
on the user name you're logged in as in Business Central.
Map users only once for each migration. If you run the
mapping twice or more, you might run into conflicts.

Setup Checklist When you're ready to use your Business Central online
tenant as your main system, the tables that weren't
migrated must be set up or defined as needed. The checklist
page shows recommended steps to complete your migration
to the cloud.

Azure Data Lake This option is available if the Business Central online tenant
is connected to Dynamics GP. For more information, see
Migrate Dynamics GP to Azure Data Lake.

Run the tool multiple times


There are some scenarios where it will be necessary for you to run the cloud migration setup guide more than
once.

TIP
We recommend that you take a backup of the target environment so that you can easily restore the environment to a
specific state and time, should you want to.

The following list highlights a few examples:


Multiple companies in Business Central on-premises
One example is if you want to add more companies to the migration, or if you want to change the
companies to migrate, run the assisted setup guide again. A more efficient option, though, is to use the
Select Companies to Migrate action from the Cloud Migration Management page.
Add tenants to an existing runtime service
If you're a hosting partner, you may have multiple tenants running on the same integration runtime
service. Each tenant will be isolated in their own data pipeline. To add tenants to an existing integration
runtime service, enter the name of the existing integration runtime service into this field. The integration
runtime name can be found in the Microsoft Integration Runtime Manager. For more information, see
Create and configure a self-hosted integration runtime in the Azure docs.
In both examples, you'll be making updates to an existing runtime service. When you get to the point of the
wizard where you can specify an existing runtime services name, open the Microsoft Integration Runtime
Service Manager and enter the runtime name in the field in the wizard; you won't be allowed to copy/paste. The
runtime service will identify that you're making updates to an existing service and won't create a new one.
Complete the steps in the wizard to update the runtime service. If the change was related to adding tenants to
an existing service, a new data pipeline will be created for that tenant. Regenerating an Azure Data Factory (ADF)
key may be done using the Cloud Migration Management page in your Business Central online. For more
information, see the Run the assisted setup guide section.

TIP
If you are using Business Central on-premises, the same setup guide is also available in your on-premises solution. You
will automatically be redirected to your Business Central online to continue the configuration process.

Cau t i on

If you have mapped users in the first run of the cloud migration setup guide, then do not choose the Define
User Mappings action again in subsequent runs.

Business Central permission sets


Specifically for migration from Business Central on-premises, we limit the amount of data that you can enter in
Business Central online to data that isn't migrated. Otherwise any data that was written to the tenant database
would be continuously overwritten during the migration process.
To make setting up this read-only tenant more efficient, we created the Intelligent Cloud user group and the
Intelligent Cloud permission set. Once the cloud migration environment is configured, all users without SUPER
permissions will be automatically assigned to the Intelligent Cloud user group. Only users with SUPER
permissions will be allowed to make modifications to the system at this point.

NOTE
Before you configure a connection from on-premises to Business Central online, make sure that at least one user in each
company is assigned SUPER permissions.

Users that are reassigned to the Intelligent Cloud user group will have access to read ALL data by default. If you
need to further restrict what data a user should be able to read, the SUPER user may create new user groups
and permissions sets and assign users accordingly. It's highly recommended to create any new permissions sets
from a copy of the Intelligent Cloud permission set and then take away permissions you don't want users to
have.

WARNING
If you grant insert, modify or delete permissions to any resource in the application that was set to read-only, it could have
a negative impact on the data in Business Central online. If this occurs, you may have to clear all your data and rerun a
full migration to correct this.

Company initialization
When a company is created in Business Central, it must be initialized to ensure it's accessible and functional for
everyone who needs to use it. If you're familiar with Dynamics NAV, then you're used to this step happening
automatically during the upgrade process, for example. But it's not quite the same with Business Central online.
When a migration run completes, you're prompted to view a list of non-initialized companies so that you can
start the initialization. You can choose to mark a company as already initialized, such as if it was initialized in an
earlier migration run. Technically, the initialization runs as a scheduled task in the job queue, and the status is
automatically updated in the list of companies when a task completes.

NOTE
When you schedule an initialization in the Hybrid Companies list, we recommend not using the company until its
initialized. The setup data could be missing, which might cause problems.

End the migration


Once you've migrated the data that you want to migrate to Business Central online, you end the migration by
disabling cloud migration in the Cloud Migration Setup page. This is an important step, because each time
someone runs the migration, outstanding documents for vendors and customers, general ledger account
numbers, inventory items, and any other changes made in the target company in Business Central online are
overwritten.

NOTE
The amount of time the migration will take to complete depends on the amount of data, your SQL configuration, and
your connection speed. Subsequent migrations will complete more quickly because only changed data is migrating.

IMPORTANT
If you set up cloud migration for an environment, the environment cannot be upgraded. If you want to upgrade the
environment, you must disable cloud migration. If you want to move more companies, set up cloud migration again once
the upgrade is complete. By separating upgrade from cloud migration, we remove the risk of potentially corrupting data if
the upgrade touches tables with records in both migrated and non-migrated companies. Upgrade the target environment
first, then migrate.

See also
FAQ about Migrating to the Cloud from On-Premises Solutions
Migrate to Business Central Online from Business Central On-premises
Migrate Dynamics GP Data to the Cloud
Upgrading from Dynamics NAV to Business Central Online
Managing Capacity
Migrate to Business Central Online from Business
Central On-premises
2/6/2023 • 5 minutes to read • Edit Online

The end-to-end process is described here. In this article, we talk about background information and things to
take into consideration.
The migration from Business Central on-premises is in two separate steps:
Data replication
This step starts when you run the Set up Cloud Migration assisted setup guide in Business Central
online. At the end of the process, you have a copy of the on-premises data in the relevant environment in
Business Central online so that you can verify if the migration went well or not. The migration task has
the status Upgrade Pending in the Cloud Migration Management page, and you can rerun the
migration multiple times if you want to.
For example, you've run the assisted setup guide from a test company in a sandbox environment because
you worry that many extensions might be problematic. Once the data has been replicated to the sandbox
environment, you can use the troubleshooting tools in the Business Central administration center, for
example.
Data upgrade
This step starts when you choose the Run Data Upgrade Now action in the Cloud Migration
Management page in Business Central online for the specific environment.
Once you have chosen this action, both the Run Migration Now and the Run Data Upgrade Now action can
no longer be used for this company in the environment. If the upgrade has failed, an automatic point-in-time
restore is run to revert the tenant to the point before upgrade. You can then fix the errors and try the upgrade
again. Alternatively, you can start the cloud migration in another environment, or you can restore the current
environment from a backup from a point in time before the data upgrade. Or, delete all companies in the current
environment and start the migration again.
If you want to migrate more companies, disable the migration, and start the setup again. Or, use the Select
Companies to Migrate action from Cloud Migration Management page.

Companies and data


The cloud migration capabilities are optimized to migrate data in batches of up to 10 companies. However, a
Business Central on-premises or Dynamics NAV database often includes more companies. In some cases, the
database contains several hundred companies.
In such cases, here are our recommendations for how to manage the migration:
Break the migration into batches.
If the companies include large data sets, break the migration into smaller batches.
For example, you're migrating 10 companies, but two companies include 50 GB each plus 30-GB shared
data. In this example, we recommend that you migrate each of the large companies individually.
Be mindful of any extensions that might complicate the migration as described in the Migrate data from
extensions section.
Check that the company names are valid. For more information, see Company names in the
Troubleshooting article.
When moving many companies, use Cloud Migration APIs.
For more information, go to Cloud Migration API Overview. Find samples in the BC Tech GitHUb repo.

Migrate data from extensions


It's highly recommended that you test the impact of any extension in a sandbox environment before you install
the extensions in your Business Central production environment to help avoid any data failures or unintended
consequences.

TIP
The migration from Business Central on-premises is in two separate steps, which gives you better options to test the
migration in a sandbox environment before you migrate to the final production environment.

In order to support data migration, tables and table extensions must specify if data from that table must be
migrated or not. By default, the ReplicateData property is set to Yes so that, by default, any extension that is
installed in the Business Central online environment will have all its tables migrated.
In certain circumstances, you may not want to migrate all data. Here are a few examples:
The extension is installed in the Business Central online environment but not in the Business Central on-
premises solution
In this case, Business Central will attempt to migrate the data but show a warning. Since the extension
isn't installed on-premises, any table related to that extension table won't migrate, and warning
notifications will appear in the cloud migration status page.
If you own the extension, we recommend that you set the ReplicateData property to No on the
extension tables. If you don't, and if you want data to migrate, install the extension in both Business
Central online and your on-premises solution. If you don't want data to migrate, uninstall the extension
from the Business Central online environment.
The extension references a base table
This can cause your base table to appear empty when you view data in your Business Central online
tenant. If that happens, uninstall the extension from your Business Central online tenant, and then run the
cloud migration process again.
Business Central will insert the default values and records into the table extensions automatically. If there
any problems, you can use the Repair Companion Table Records action on the Cloud Migration
Management page to insert the missing table extension records.

TIP
Use the Cloud Migration Management page to verify that data migrated correctly. For example, an extension extends
a table in the base application. In SQL Server, the table doesn't contain the data from the base app table for some reason.
In this example, the Cloud Migration Management page shows the table as not migrated, and the page that renders
the table is blank. The solution is to verify on-premises that the table with the table extension contains the same count of
records as the table for the base app table.

For more information, see FAQ about Migrating to Business Central Online from On-Premises Solutions and
Troubleshooting Cloud Migration.

Data that isn't migrated


During the data migration process, Business Central doesn't migrate most system tables, users, and permissions.

NOTE
Currently, record links are not migrated because the links are associated with a user ID, and we do not migrate users from
the on-premises environment to the online tenant. You can choose to upvote this feature suggestion.

Upgrading to a new version of Business Central


If you upgrade to a new version of Business Central on-premises, including a cumulative update, then you must
update the extensions as well. Depending on your on-premises solution, your Business Central online
environment contains different extensions for the cloud migration. For more information, see Business Central
Cloud Migration Extensions.

See also
Run the assisted setup guide
Migration On-premises Data to Business Central online
ReplicateData Property
Intelligent Insights with Business Central Online
Migrate Legacy Help to the Dynamics 365 Business Central Format
Upgrading from Dynamics NAV to Business Central Online
Important Information and Considerations for Before Upgrading to Dynamics 365 Business Central Spring 2019
Migrate Dynamics GP Data to the Cloud
2/6/2023 • 13 minutes to read • Edit Online

An assisted setup guide in Business Central can help you migrate data from Dynamics GP. You can migrate data
from Dynamics GP 2015 and later versions of Dynamics GP. For more information, see System requirements.

IMPORTANT
Migrating from Dynamics GP using the Cloud Migration Setup assisted setup guide is currently only supported for the
following markets: United States, Canada, United Kingdom, Australia.

The end-to-end process is described here. In this article, we talk about background information and things to
take into consideration.
As part of the Business Central 21.1 release, company settings for data migration have been moved from the
Cloud Migration Setup Wizard and placed in a new GP Company Migration Configuration page. This page
allows for improved ease of use by allowing you to make global settings for all companies selected to migrate
with the ability to update at a company level if necessary. You can access the GP Company Migration
Configuration page from Migration Management.
In addition to the GP Company Migration Configuration page you can select which modules you would like
migrated from GP to Business Central. You will be able to select from the following modules to migrate:
Accounts Payable, Accounts Receivable, Bank, Open Purchase Orders and Inventory.
Note: General Ledger information will always be migrated.

Dynamics GP data
Business Central update 21.1 adds a new page, GP Company Migration Configuration . Use this new page to
select the data you want migrated from Dynamics GP to Business Central. The page will automatically open after
you complete the Cloud Migration Setup wizard, but you can also open it from the Cloud Migration
Management page.
New options such as selecting what modules you want to migrate as well as if you only want to migrate master
data for specific modules are available. You can select the options at a global level, applying the options to all
companies selected to migrate or you can tweak options at a company level in the Per Company fast tab.
If you select to only migrate master data, records such as Accounts, Customer, Vendors and Items will migrate,
however no transactional information from GP will be migrated for the selected module.
When you migrate from Dynamics GP, the following information is migrated from Dynamics GP to Business
Central online:
1. Fiscal periods
The fiscal periods setup in Dynamics GP will be migrated to Business Central as accounting periods. Any
years marked as historical in Dynamics GP will come over to Business Central as open and will must be
closed in Business Central. If any adjustments need to be made to historical years after migrating, those
adjustments can be done before closing the year.
2. Chart of Accounts master records
The account number in Business Central will be mapped from the main account segment from Dynamics
GP. Remaining account segments are then defined as dimensions in Business Central. The GP Company
Migration Configuration asks the user to enter a segment for Global Dimension 1 and Global Dimension
2. If your chart of accounts in Dynamics GP has more than 2 segments outside of the main segment, the
other segments are automatically set up as shortcut dimensions (3-8). You can verify the setup in the
General Ledger Setup page in Business Central.
Let us look at an example of an account from Dynamics GP, using the year 2022 as an example:

A C C O UN T IN DY N A M IC S
GP Y EA R NAME A M O UN T

000-1100-00 Cash Yes 2022

Period 1 250.00

Period 2 117.00

Period 3 340.00

000-1100-01 Cash Yes 2022

Period 1 240.00

Period 2 102.00

Period 3 501.00

000-4000-00 Sales Yes 2022

Period 1 490.00

Period 2 219.00

Period 3 841.00

The migration creates two accounts in Business Central, number 1100 and number 4000. New
dimensions are also added with the names 000, 00, and 01. General journal transactions are created as
follows:

T RA N SA C T IO N DAT E A C C O UN T N O. A M O UN T DIM EN SIO N S

1/31/2022 1100 250.00 Dimension 000, 00

1/31/2022 1100 240.00 Dimension 000, 01

1/31/2022 4000 490.00 Dimension 000, 00

2/28/2022 1100 117.00 Dimension 000, 00

2/28/2022 1100 102.00 Dimension 000, 01

2/28/2022 4000 219.00 Dimension 000, 00


T RA N SA C T IO N DAT E A C C O UN T N O. A M O UN T DIM EN SIO N S

3/31/2022 1100 340.00 Dimension 000, 00

3/31/2022 1100 501.00 Dimension 000, 01

3/31/2022 4000 841.00 Dimension 000, 00

The data migration generates dimensions on that account based on the different segments. User will see
a Department dimension with the values 000, 100, and 200, respectively. A second dimension, Division,
will show the values 00, 01, and 02, respectively.
Account summary transactions are generated and posted for open and history years that were set up in
Dynamics GP. The summary amounts are created based on the fiscal periods set up in Dynamics GP. In the
GP Company Migration Configuration page, you can select the oldest historical year you want migrated
to Business Central. For example, if 2019, 2020, and 2021 are historical years in Dynamics GP, you could
select that the oldest historical year you want migrated is 2020. Summary transactions for 2019 would
not be migrated to Business Central.
3. Customer master records and outstanding transactions from the Receivables module
In the GP Company Migration Configuration page, you can choose to migrate all customers from
Dynamics GP or only active customers. This allows you to not migrate over customers that have been
marked as inactive. We also have added bringing all addresses from the customer over into Business
Central. All of the addresses on the customer will be setup as shipping addresses in Business Central. That
will allow the end user to choose the address needed when entering transactions after the migration.
In the GP Company Migration Configuration page, you can also choose to migration posting accounts on
customer classes. If you choose this option, posting accounts defined on customer classes in Dynamics
GP will be migrated to Business Central as customer posting groups. If a customer is assigned to a
customer class in Dynamics GP, the customer will be assigned to the corresponding customer posting
group after migrating.
We also bring over outstanding receivables transactions. These transactions will be brought in with the
amount remaining in Dynamics GP. For example, if an invoice for $1000 was entered into Dynamics GP,
and it has been partially paid and has a remaining balance of $400, the new invoice created in Business
Central will be for $600 as that is the amount remaining to be paid. We bring over all transaction types
from Receivables Management.
4. Vendor master records and outstanding transactions from the Payables module
In the GP Company Migration Configuration page, you can choose to migrate all vendors from Dynamics
GP or only active vendors. This allows you to not migrate over vendors that have been marked as
inactive. We also have added bringing all addresses from the vendor over into Business Central. All
vendor addresses from the vendor are migrated to Business Central. The vendor's Remit To Address will
be the main address for the vendor. All other vendor addresses will be setup as Order addresses in
Business Central. That will allow the end user to choose the address needed when entering transactions
after the migration.
In the GP Company Migration Configuration page, you can also choose to migrate posting accounts on
vendor classes. If you choose this option, posting accounts defined on vendor classes in Dynamics GP will
be migrated to Business Central as vendor posting groups. If a vendor is assigned to a vendor class in
Dynamics GP, the vendor will be assigned to the corresponding vendor posting group after migrating.
Vendor EFT Bank information will be migrated to Business Central as Vendor Bank Accounts. If a Vendor's
Remit to address contains EFT Bank information in Dynamics GP, it will be migrated over as the Preferred
Bank Account Code on a vendor in Business Central.
We also bring over outstanding Payables transactions. These transactions will be brought in with the
amount remaining in Dynamics GP. For example, if an invoice for $1000 was entered into Dynamics GP,
and it has been partially paid and has a remaining balance of $400, the new invoice created in Business
Central will be for $600 as that is the amount remaining to be paid. We bring over all transaction types
from Payables Management.
You can also bring over Open Purchase Orders. When we migrate purchase orders, we are looking at the
items and the quantities remaining on those items to determine what we will bring over as an open
purchase order. If an item is fully received and invoiced that item will not migrate. By bringing over open
purchase orders, you do not have to enter outstanding transactions from the purchase order aspect.
5. Inventory items
Inventory is imported with the cost valuation method that is set in GP at the time the migration is run.
Location information as well as the quantity on hand for each time is migrated. If serial or lot information
is tracked on an item, that information is also migrated.
In the GP Company Migration Configuration page, you can choose to migrate posting accounts on item
classes. If you choose this option, posting accounts that are defined on item classes in Dynamics GP will
be migrated to Business Central as inventory posting groups. If an item is assigned to an item class in
Dynamics GP, the item will be assigned to the corresponding inventory posting group after migrating. If
you only want to migrate active items you can choose to exclude inactive items in the GP Company
Migration Configuration page. Additional, you can choose if you do not want to migrate discontinued
items.
6. Checkbook transaction and master data
You can choose to migrate all checkbooks from Dynamics GP or only active checkbooks. Unreconciled
bank transactions will be migrated to Business Central so that you can reconcile your checkbooks after
migrating. Any cash receipt that has been posted should also be deposited in GP before migrating, as
undeposited receipts will not migrate.
7. GP Historical Snapshot
In the GP Company Migration Configuration page you can select if you want to migrate historical
information from GP into Business Central. This data will be visible in listpages found under the
corresponding entities and navigating to GP Detail Snapshot. You can indicate if you want to migrate GL
detail, Receivables, Payables, Sales Order Processing, Purchase Order Receipts and Inventory transactions.
The data is stored in extension tables in Business Central. Data stored in those tables can be used in
Power BI reports, Power Apps or other 3rd party reporting tools. The tables containing the GP Historical
Snapshot data are as follows:
Hist. G/L Account
Hist. Gen. Journal Line
Hist. Payables Document
Hist. Receivables Document
Hist. Sales Trx. Header
Hist. Sales Trx. Line
Hist. Purchase Recv. Header
Hist. Purchase Recv. Line
Hist. Inventory Trx. Header
Hist. Inventory Trx. Line
You can limit the about of data migrated in the snapshot by entering the latest year in GP that you want
brought over. Enter this year in the Oldest GP Year field in the GP Company Migration Configuration
page.
The GP Historical Snapshot will run as a background process after the migration is complete. The status
of the GP Historical Snapshot data can be viewed in Fact boxes in the Cloud Migration Management page.

Diagnostics run
In the Cloud Migration Management page, you can create a diagnostics run to do more data
validation/verification before the migration is run so that you can decrease the risk of a failed migration.
The maximum field length is different in Dynamics GP (30) and Business Central (20), and the diagnostics run
checks for issues and shows warnings. The tool also checks item numbers to look for duplicates based on the
character limit, and it checks to make sure there are no blank posting accounts that are needed for posting of
transactions with the migration.
Here is an example of what you might see when you run a diagnostic run:

Migration tool support for Australia


Starting with 2020 release wave 2, organizations in Australia can migrate from Dynamics GP to an Australian
version of Business Central online.
The process to run the migration in an Australian Business Central online is the same as running a migration in
the other supported countries. However, there is some setup that needs to be done before the migration can be
run. To make the changes to the setup, you must run through the cloud migration wizard. When the wizard
setup is complete, and companies are fully set up, you must log into the companies that you are planning to
migrate and make the following changes
Transactions
With transactions that are being migrated, we bring over totals on the invoices for the customers so GST
information is already included in the transactions. You must turn off the GST and Adjustment Mandatory
features in the General Ledger Setup page to allow the transactions to post during the migration. After
the migration is complete, you can turn both GSP and Adjustment Mandatory back on so that new
transactions that are entered in Business Central online will use this functionality.
Posting groups
Within the posting process there is validation to look for a blank VAT business posting group and VAT
product posting group. This combination isn't setup by default and is needed for the migration. So add a
VAT posting configuration in the VAT Posting Setup page with blank values for the VAT Bus Posting
Group and VAT Prod. Posting Group fields.

Move your Dynamics GP database to Azure Data Lake


Starting with 2020 release wave 2, you can create a copy of the Dynamics GP database in Azure Data Lake so
that you have it for future reference after the migration to Business Central online. To take advantage of this
functionality, there are some pieces that must be set up before the migration process. A customer is not required
to copy their database to Azure Data Lake, but there are several benefits to being able to do so, including having
access to the historical data that is not migrated by the migration tool. For an introduction to Azure Data Lake,
see azure.microsoft.com.
To create an Azure Data Lake storage account, you log in to your Azure subscription (or sign up for an Azure
subscription). Once logged into the Azure portal, you can create a storage account. Under the Access Keys
section of the information about your storage account in the Azure portal, you can see the keys that you must
provide in the cloud migration wizard in Business Central. For more information about Azure Data Lake and
setting up a storage account, see Azure documentation.

To move to Azure Data Lake


1. In your Business Central online tenant, choose the icon, enter Cloud Migration Management , and
then choose the related link.
2. Choose the Azure Data Lake action.
The Azure Data Lake Migration Setup guide takes you through the steps to connect your on-
premises Dynamics GP database and your storage in Azure Data Lake. You must have created an Azure
Data Lake storage account (v2) before launching the assisted setup, and you must have access to the
storage account name and storage account key.
3. When the setup completes, you can monitor the progress of moving your data from on-premises to
Azure Data Lake in the Cloud Migration Management page in Business Central.
If you go back to the Azure portal, you can see the data that was moved from your Dynamics GP database to
Azure Data Lake. Under the containers section of the Data Lake storage, a new gp-database folder contains the
company/system databases, and sub-folders contain the series folder and data files.
The database folder in Azure Data Lake will always be set as gp-database. If you want to rename it, you can do
so after the migration has competed. The same applies to the various sub-folders. The folders created follow the
standard naming convention of the series folders in Dynamics GP. An additional folder, 3rd Party, will be created,
and any files that haven't be mapped to a folder will reside in there. You can modify the content in the folders
after the migration has completed.
If an Azure Data Lake migration has already been run in the Business Central company and you launch a second
run, the migration tool will check to see if a gp-database folder exists. If you still want to run the migration again,
you must delete the gp-database folder and its contents before you can run the wizard again.
At the end of the migration, you have a completely copy of your Dynamics GP database in the cloud with all the
advantages of having access to historical data without having to maintain a server on-premises.

See also
Run the assisted setup guide
Compare Work in Dynamics GP to Business Central
Migrating On-Premises Data to Business Central Online
Troubleshooting Cloud Migration
FAQ about Migrating to Business Central Online from On-Premises Solutions
Important Information and Considerations for
Before Upgrading to Dynamics 365 Business Central
Spring 2019 and Later Versions
2/6/2023 • 5 minutes to read • Edit Online

Depending on which version you are upgrading from, and the degree to which your solution differs from the
standard version of Business Central, you may want to prepare your solution for the upgrade. This topic
provides important information and tips for things to consider when you prepare to upgrade to Business
Central.

Migrate from Dynamics NAV to Business Central online


You can upgrade to Business Central online from supported versions of Dynamics NAV on-premises, provided
that your application customization is handled by extensions. Any data from tables with code customizations
cannot be carried forward from Dynamics NAV.

NOTE
Upgrade your solution to Business Central Spring 2019 (version 14) or later, and then migrate to Business Central online.

The process consists of two parts:


Upgrade from Dynamics NAV to Business Central using the tools described in Upgrading to Business Central
on-premises (version 14). For more information, see Supported Upgrade Paths to Dynamics 365 Business
Central Releases.
Convert non-standard functionality and customizations to apps and per-tenant extensions. For more
information, see Deploying a Tenant Customization.
Run the cloud migration tool as described in Migrate On-Premises Data to Business Central Online, and then
switch to use Business Central online going forward.

Upgrading from Dynamics NAV


This section lists specific changes between Dynamics NAV and Business Central.
Codeunit 1 has been deprecated and replaced
Dynamics NAV included codeunit 1 ApplicationManagement . In Business Central, this codeunit has been
retired, and new 'system' codeunits have been introduced in the 2 billion range.
For information, see Transitioning from Codeunit 1 to System Codeunits.
V1 Extensions have been discontinued
With Business Central, extensions V1 are no longer supported for on-premise installations. As a result, any
custom extensions V1 must be converted to extensions V2 in the old environment before upgrading to Business
Central.
For information about how to convert to extensions V2, see Converting Extensions V1 to Extensions V2.
MenuSuite not used for page and report search
With Business Central, the MenuSuite is no longer used to control whether a page or report can be found in the
search feature of the Web client. This is now determined by specific properties on the page and report objects.
As part of the application code upgrade process, you change these properties on existing pages and reports
used by the MenuSuite to ensure that they are still searchable from the Web client. For more information, see
Making Pages and Reports Searchable After an Upgrade.

Dynamics 365 Sales integration


Because of changes in Dynamics 365 Sales and the integration since previous releases, if your application is
integrating with Dynamics 365 Sales, then you must perform a full upgrade instead of just a technical upgrade.

New and changed application features


There are several new and changed application features available in Business Central April 2019 for users,
administrators, and developers. For an overview of these features, see Overview of Dynamics 365 Business
Central April '19 release.
To take advantage of these all these features, you will have to perform an application code upgrade, not just a
technical (platform) upgrade.
Changes to profiles in the CRONUS International Ltd. demonstration database and promoted actions
With the Business Central April 2019 release, profiles that are part of the CRONUS International Ltd.
demonstration database, such as the Sales Order Processor profile, customize fewer pages compared to
earlier releases. For customers that rely on these profiles, their users might experience slight differences in the
layout of actions in the action bar on pages. Additionally, the layout of promoted actions on over 380 core
application pages has been fine-tuned.
To ensure that users are not disrupted by these changes, we recommend that administrators and partners who
are upgrading a customer to Business Central April 2019, review the layout of promoted actions when
combined with their own code and profile customization.

Names of variables
Business Central introduces new methods and statements. If your solution includes variables where the name is
now used by a standard AL method or statement such as REGISTERTABLECONNECTION or FOREACH, you must
change the variables before you upgrade to Business Central. Alternatively, you can enclose the variable names
in quotation marks. If you do not, and you import an object that has this code in text format, you cannot compile
the object.

Deprecated or redesigned functionality


If you are upgrading a solution that depends on functionality that is deprecated or changed in the default
version of Business Central, you must verify that the upgrade codeunits migrate data correctly. See the See Also
section for links to descriptions of deprecated functionality.

Deprecated fields and fields marked as obsolete


Sometimes Microsoft will refactor code so that fields are no longer used, or the functionality is moved from the
base application to an extension, for example. Typically, the upgrade toolkit will manage the upgrade impact, but
for transparency, you can find a list of fields that are deprecated in the current release or marked to be obsolete
in a later release. For more information, see Deprecated Fields, and Fields Marked as Obsolete.

Upgrade codeunits
When you introduce changes to the database schema, Business Central will check if these changes are
destructive or not. If the database check indicates that the change may lead to data deletion, such as if you are
dropping a table column so that the contents of that column will be deleted, this is considered a destructive
change. You will be prompted to handle the situation using upgrade codeunits.

Company names
If a company name includes a special character, an error may display during the upgrade. In this context, special
characters include the following:
[~@#$%&*().!%-+/=?]
If you are going to upgrade a database where one or more company name includes a special character, we
recommend that you rename the company before you start the upgrade process. After the upgrade is
successfully finished, you can rename the company again.

System tables with non-English names


In older versions of Dynamics NAV, you could translate the columns in system tables to a language other than
English. Starting with version 3.0, we advised heavily against this, and versions later than Microsoft Dynamics
NAV 2013 R2 require that all columns in all system tables are in English. As a result, if you try to open a
database with non-English system tables in Microsoft Dynamics NAV 2013 R2 or later, an error displays, saying
that one or more columns do not exist.
Make sure that all objects where compiled in a development environment with the right .ETX and .STX files. You
can verify that you are running in the correct environment with English (US) as the base language by opening
the ndo$dbproper ty table in SQL Server Management Studio. In the Identifiers column, the word Object
must be written exactly as shown here.

See Also
Upgrading the Application Code
Upgrading the Data
Deprecated Fields, and Fields Marked as Obsolete
Define Migration Table Mappings
2/6/2023 • 4 minutes to read • Edit Online

Migration table mapping can be used to rename the table during the cloud migration or to move a subset of
fields to a different table or table extension. Before you start defining table mapping

TIP
You can use the Impor t and Expor t actions to import or export the definition done in the UI.

Design constraints
It's not possible to have multiple source tables mapping to the same destination (target) table. The destination
table must have a single on-premises source table.
For example, the following mappings together aren't supported:

SO URC E TA B L E DEST IN AT IO N TA B L E

Customer MyTable

MyTable MyTable

But the following mappings are supported:

SO URC E TA B L E DEST IN AT IO N TA B L E

Customer Customer

Customer MyTable

This limitation also applies to tables that are automatically included into the replication, which means tables
enabled for cloud migration by the ReplicateData property. If these tables exist in the on-premises database,
they'll automatically be included in the clod migration. So, no table mappings can define these tables the
destination table.

Rename the table during the cloud migration


This scenario supports adding the prefix or changing the table name during cloud migration.
For example, suppose the Business Central on-premises table is named My Custom Table . But in Business
Central online, the name needs to be prefixed (or suffixed) with 3 letters, so the table name is ABC My Custom
Table .
Prerequisites
The keys in on-premises table and online table must match.
The online target table must have the ReplicateData property set to true .
Create the table mapping for renaming
1. Sign in to Business Cental online.
2. Search for and open the Cloud Migration Management page.
3. Select Manage Custom Tables to open the Migration Table Mapping page.
4. Set the following fields:

F IEL DS VA L UE

Target Type Table

Extension Names Set to the name of the extension that contains the table.

Table Name Set to the table in the extension. Setting these three
fields specifies the target table.

Source Table Name Enter the full name as it appears in SQL. The system will
parse the values.

C/AL table example:


[CRONUS COMPANY$ABC My Custom Table]

AL table example:
[CRONUS COMPANY$ABC My Custom Table$437dbf0e-
84ff-417a-965d-ed2bb9650972]
. The GUID 437dbf0e-84ff-417a-965d-ed2bb9650972 is
the extension ID, which in this case is for base app.

The following figure illustrates an example of the Migrate Table Mappings page for an AL table:

Move a set of fields out of the main table to another table or table
extension
NOTE
This type of table mapping is only supported for cloud migrations from Business Central. Dynamics GP and SL don't
support table extensions.

For example, suppose that you've added two custom fields to the Customer table in Business Central on-
premises. You want to move these two custom fields to a table extension in Business Central online. If you define
a table extension mapping, then the engine will move a subset of fields to the table extension.
Prerequisite
Fields to be moved to a table extension must have the same name and type as in the source table in the
Business Central. If the name is different, the fields will be ignored by the engine, and won't be moved to
Business Central online.
Create the table mapping for moving fields
1. To create the table mapping, follow the same steps as in Scenario 1, except set the Target Table Type to
Table Extension .
2. If you're moving a table that is per-database table, clear the Data Per Company check box.
The following figure illustrates an example of the Migrate Table Mappings page for a C/AL table:

Add multiple table mappings


Follow these steps if you need multiple table mappings.
1. On the Migration Table Mapping page, select Add Table Mappings .
2. On the Add Migrate Table Mappings page, in the Source Table section, enter the table name in the
Name field.
It's best to enter the full name as it appears in SQL Management Studio as in the following examples:
C/AL table: [CRONUS COMPANY$ABC My Custom Table]

AL table: [CRONUS COMPANY$ABC My Custom Table$437dbf0e-84ff-417a-965d-ed2bb9650972]

The GUID 437dbf0e-84ff-417a-965d-ed2bb9650972 is the extension ID, which in this case is for base app.
3. To set the target table, go to the Target Table section and set the Type to Table or Extension .
The list shows all the tables available for mapping to the target table. You can filter the list by setting an
extension in the Extension Name field.
4. Select all rows that you want to map to the target table.
The following figure illustrates an example of the Add Migrate Table Mappings page:
5. Close the page.
After closing the page, the multiple table mappings will be inserted. This step is useful when you want to
split a single source table into multiple table extensions.

Provide table mappings programmatically


We recommend that you provide the table mappings programmatically. To do table mappings
programmatically, subscribe to OnInsertDefaultTableMappings event from codeunit 4001 "Hybrid Cloud
Management".
Table mappings will be inserted after the setup wizard is completed or if you run the Restore Default
Mappings from Migration Table Mapping page.

See also
Migrate Data
FAQ about Migrating to Business Central Online
from On-Premises Solutions
2/6/2023 • 5 minutes to read • Edit Online

This section contains answers to frequently asked questions about migrating from on-premises solutions to
Business Central online.

TIP
Check the tips in this article if your organization is not yet ready to migrate to Business Central online but are thinking
hard about it. For more information about migration, see Migrate On-Premises Data to Business Central Online.

Which products and versions are supported?


You can use the built-in migration tools to migrate data to Business Central online from specific product
versions. The on-premises solution must use SQL Server 2016 or a later version, and the database must have
compatibility level 130 or higher. Currently, you can migrate to Business Central online from the following
products:
Dynamics GP 2015 and later versions
Business Central on-premises
Currently, you can migrate to Business Central online from the earlier versions 14 through 20. For an
indication of compatibility across minor versions, see here. You can also switch to online from the current
version (21).
If you are currently on a version of Dynamics NAV, you must upgrade to Business Central on-premises, and then
switch to Business Central online. For more information, see Upgrading from Dynamics NAV to Business Central
online.
System requirements
To migrate to Business Central online, the on-premises solution must use SQL Server 2016 or a later version,
and the database must have compatibility level 130 or higher. The on-premises solution must also be one of the
supported versions.
For comparison, see the System Requirements for Dynamics 365 Business Central (on-premises) 2021 Release
Wave 1 and subsequent versions.

How is my on-premises data migrated to my Business Central online


tenant?
Data is migrated using an Azure service called Azure Data Factory (ADF). ADF is a service that is always running
within the Business Central online service manager. When you start the cloud migration, a data pipeline is
created in the ADF service so that data can flow from your on-premises solution to your Business Central online
tenant. If your data source is a local SQL Server instance, you'll also be asked to configure a self-hosted
integration runtime (SHIR). The runtime is installed locally and manages the communication between the cloud
services and your on-premises data without opening any ports or firewalls.
Are there any limits on the amount or type of data that will migrate?
There are no restrictions on the type of data that can be migrated. By default, Business Central customers can
use up to 80 GB of database storage capacity across all their environments (production and sandbox). This limit
means that the sum of database capacity usage across all of their environments must not exceed 80 GB. If a
tenant exceeds this limit, Microsoft restricts administrative actions that create additional environments.
Exceeding the storage limit will not interrupt transaction processing within the existing environments.Some
businesses have unique scenarios that may require additional storage. For those organizations that need more
space, there's an option to purchase extra database capacity.
We recommend that you reduce the number of companies that you're migrating data for in each migration run.
You can specify which companies to include in the migration in the assisted setup wizard.
If you want to add more companies after the first selection of companies, you can add more companies in the
Cloud Migration Management page in Business Central online. For more information, see Run the tool
multiple times.
If you're looking at migrating databases larger than 80 GB, we recommend that you contact the support team
and work with them to make sure that the migration is successful. If needed, you can also purchase more
storage. For more information, go to Managing Capacity.

Is my SQL connection string required to set up the connection?


Yes. The SQL connection string is passed to Azure Data Factory, where it's encrypted and delivered to your Self-
Hosted Integration Runtime. The connection string is used to communicate with your SQL Server instance
during the data replication process. For more information, see How do I find my SQL connection string?.

How do I find my SQL connection string?


Find the connection string to your SQL database in SQL Management Studio or Visual Studio. The user name
and password defined in the connection requires a SQL Authenticated user name/password. Your connection
string will look something like this:
Server=tcp:{ServerName},1433;Initial Catalog={DatabaseName};Persist Security Info=False; User ID=
{UserName};Password=
{Password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;

How do I find the Integration Runtime name?


Find the Integration Runtime name in the Microsoft Integration Runtime Manager, which you can find in your
Windows system tray or by searching for the program. You must type the name. You won't be able to copy and
paste the name.

I'm a hosting partner - do I need to configure the Self-Hosted


Runtime Service for each tenant?
No, there's no limit on the number of tenants that can be added to your Self-Hosted Integration Runtime. Each
added tenant will have a dedicated pipeline created.

Will data from tables with code customizations migrate?


No, only tables that are available in both your on-premises solution and your Business Central online tenant will
migrate. Any customization must be made into an extension and installed on both your on-premises solution
and your Business Central online tenant to replicate.
Yes, but it requires that someone defines tables mappings to move the customized fields. For more information,
go to Define Migration Table Mappings.

Why are my permissions restricted in the Business Central online


tenant?
When you connect your on-premises solution to Business Central online as part of the migration, all existing
users are automatically added to the Intelligent Cloud user group, unless they have the SUPER permission set. In
this configuration, your on-premises solution is the master where all business transactions take place. The
Business Central online environment is read-only, and the data is used to generate intelligent business insights
based on your on-premises data for you. We restrict permissions to prevent users from accidentally entering
transactions or updating master records only to have that information overwritten and lost when data
replication takes place. Once the migration is complete, you can assign the relevant permissions to all users and
stop using your on-premises solution.

Will my on-premises users and permissions replicate?


No. Since you aren't required to configure your on-premises solution with Azure Active Directory (Azure AD), we
can't guarantee a mapping between on-premises users and users in your Business Central online tenant.
Business Central online requires Azure AD accounts, and users must be manually added. All permissions must
be granted in the Business Central tenant, independent from your on-premises permissions.
For more information, see Managing Users and Permissions.

Is the data replication only one way?


Yes, data is only replicated from the on-premises solution to your Business Central online tenant for the
purposes of migration. Once you start using Business Central online, you must stop using your on-premises
solution.

Should I uninstall all my Business Central extensions?


No. But if your cloud migration includes data upgrade of a large amount of data, we recommend that you
uninstall the extensions that that include any data to move. It will speed up the upgrade and overall cloud
migration process. You can reinstall the extensions after the migration.

See also
Troubleshooting Cloud Migration
Migrating On-Premises Data to Business Central Online
Troubleshooting Cloud Migration
2/6/2023 • 8 minutes to read • Edit Online

In this article, you learn how to troubleshoot problems that you may experience with the cloud migration of
Business Central. For the cloud migration to work properly, there are certain requirements that must be met on
the online and on-premises databases. The following sections talk about these requirements, how you can check
them, and correct them as needed.

SQL Server compatibility level


Database: on-premises

The SQL Server compatibility level must be 130 or higher.


To check the compatibility level run following query:

SELECT compatibility_level FROM sys.databases WHERE name = 'YourDatabaseName';

If your on-premises SQL Server instance is a supported version that allows you to change the compatibility
level, you can do so with the following query. If you're using a different version, you must upgrade your current
on-premises environment to meet the current SQL Server compatibility requirements. For more information,
see View or Change the Compatibility Level of a Database

ALTER DATABASE YourDatabaseName SET COMPATIBILITY_LEVEL = 130;

NOTE
You may also get the following error when compatibility level isn't set to the expected value: A database operation failed
with the following error: Invalid length parameter passed to the LEFT or SUBSTRING function.

Migration user
Database: on-premises

Make sure that the database user that the Integration Runtime uses to connect to your database has access to
the database.
You can verify the database user, for example, by running the following command using Microsoft PowerShell
ISE.

sqlcmd -S 'ServerName\ServerInstance' -d 'DatabaseName' -U 'UserID' -P 'Password' -Q 'select * from [dbo].


[CRONUS USA, Inc_$Accounting Period$437dbf0e-84ff-417a-965d-ed2bb9650972]'

Change tracking
Database: on-premises
Change tracking must be enabled on the database. It should be enabled automatically. However, if you see an
error like Change tracking is not enabled on table <number> during migration, you'll have to enable it
manually.
To enable change tracking on your database, run the following query:

ALTER DATABASE [YOUR DATABASE] SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON)

To enable change tracking on specific tables, run the following query:

ALTER TABLE [YOUR TABLE] ENABLE CHANGE_TRACKING

Insufficient user permissions (Business Central and SQL Server users)


Database: online

If a user has problems managing a cloud migration, like starting migration, initializing companies, or migrating
data from earlier versions, check that:
The user has a Business Central license (Essentials or Premium, depending on their solution). We recommend
using free Dynamics 365 Business Central Premium Trial subscription for this user.
The user is assigned the SUPER permission set.
Users without a license, such as internal administrators or delegated administrators, aren't allowed to run the
migration.

Self-Hosted Integration Runtime


Database: on-premises

Ensure that you're running the latest, compatible version of Microsoft Integration Runtime (IR).
You can check for and download the latest version from the Microsoft Download Center.
When downloading and installing Integration Runtime, choose version 5 (IntegrationRuntime_5.x.x.x.msi)
only if your machine runs .NET Framework Runtime 4.7.2. Otherwise, or if in doubt, choose version 4
(IntegrationRuntime_4.x.x.x.msi).

IMPORTANT
Running Integration Runtime v5 on a machine that doesn't have .NET Framework Runtime 4.7.2 can cause
timeouts when connecting to the on-premise SQL Server, which will break the cloud migration setup.

Before you install a new Integration Runtime version, uninstall the old version. When you uninstall the
old version, choose to delete the user data (such as authentication key and data source credentials) when
prompted. Then, install the Integration Runtime again and connect it to the online environment using the
new authentication key.
If you get a "Failed to enable your replication." error when running theData Migration Setup assisted
setup, check the IR logs.
You view the logs by using the Microsoft Integration Runtime Configuration Manager , which was
installed on-premises as part of the IR installation. Launch Microsoft Integration Runtime
Configuration Manager , select the Diagnostics tab, then select View Logs action. You can also use
the Test Connection feature on the page to verify that your user can connect to the database.
Synchronization errors can sometimes occur because IR is installed on a laptop or desktop computer
where the hibernate feature is turned on.
The computer where IR is installed ideally shouldn't be switched off, go to sleep, or hibernate. If these
conditions happen, the IR may get into an error state. In this case, we recommend that you reinstall the IR
and turn off sleep hibernate on the computer.
Make sure the machine, which you use for hosting IR has plenty of memory (RAM) available. Migration
can be interrupted by your machine running out of memory, and you can find this issue described in the
IR log. To prevent this situation, avoid running too many migrations simultaneously using the same IR.
Every extra parallel migration slows down the overall progress considerably.
If you experience problems with Microsoft Integration Runtime, also see Troubleshoot self-hosted integration
runtime.

Migrating between multiple source and destination databases


Database: online and on-premises

If you migrate several on-premises databases to several online environments, it's possible to reuse the
same IR for these migrations.
Once you've successfully connected and migrated data into one online environment, you can reuse the IR
for another environment. To reuse an IR, enter its name in Integration Runtime Name field of Data
Migration Setup assisted setup, instead of leaving the field blank.
Use a restored backup when migrating the same on-premises database to different online environments.
Cloud migration stores some data in the on-premises database. So using the same on-premises database
to migrate into another online environment can affect the next synchronization run. If you need to
migrate to several online environments, we recommend you make a backup of the on-premises database
before enabling the data migration. Then, restore the on-premises database to this backup before setting
up migration to another online environment.
Avoid running several migrations of the same on-premises database to different online environment at
the same time.
If you need to do this type of migration, then migrate data sequentially. First, migrate data into the online
environment and disable the migration. Then restore the on-premises database from backup and enable
the migration again by providing a connection string to this database. You can use the same Integration
Runtime and Authorization key.
Don't try to migrate data from several on-premises databases into the same online environment at the
same time.
For example, you may have two companies, where each company is in its own on-premises database. If
you need to do this type of migration, the migrate data sequentially. First, migrate data from one
database into the online environment and disable the migration. Then set up the migration in the same
online environment, provide a new connection string to the next on-premises database. You can use the
same Integration Runtime and Authorization key.

Product version
Database: online

When running the Data Migration Setup assisted setup, make sure to select the right product that you
want to migrate from. Depending on which Cloud Migration apps you've installed, the assisted setup will
let you choose from three options:

O P T IO N W H EN TO USE

Dynamics 365 Business Central current version Select this option if you're migrating from the Business
Central latest version.

Dynamics 365 Business Central earlier versions Select this option if you're migrating from an earlier
supported version. Currently, you can migrate to
Business Central online from the earlier versions 14
through 20. For an indication of compatibility across
minor versions, see here. You can also switch to online
from the current version (21).

Dynamics GP Select this option if you're migrating from the Dynamics


GP product.

When migrating data from Business Central, check the applicationVersion field in the
$ndo$tenantdatabaseproperty table. Set this field to the correct version in the SQL if it's blank or not up to
date. The migration code uses the field's value for the following reasons:
Verifies that you're migrating from a supported version
Verifies that you've selected the right product version in the Data Migration Setup assisted
setup, Dynamics 365 Business Central current version or Dynamics 365 Business
Central earlier versions .
Determines which upgrade code will be executed.
If that field is blank, the migration can't run.

Company names
The cloud migration process can become difficult if the names of the companies in Business Central on-
premises or Dynamics NAV include special characters or trailing spaces, for example. To test that the company
names are valid, run a query in the on-premises database such as the following:

SELECT *
FROM Company

Where ([Name] like '% ') or ([Name] like ' %' ) or ([Name] like '%' + Char(10) + '%') or ([Name ] like '%' +
Char(13) + '%') or ([Name ] like '%/%' )

Change the company name, run the migration, and then, when migration is complete, change the company
name in the target environment as appropriate.

Missing or corrupted data after cloud migration


Database: on-premises

If cloud migration has completed successfully, but pages in Business Central online aren't showing the expected
data, or there are duplicate record exceptions thrown for setup tables, it's most likely due to table extensions
missing records that are present in the base application.
For example, an extension extends a table in the base application. In SQL Server, the table doesn't contain the
data from the base app table for some reason. In this example, the Cloud Migration Management page
shows the table as not migrated, and the page that renders the table is blank. The solution is to verify on-
premises that the table with the table extension contains the same count of records as the table for the base app
table.
To fix this problem, go to the Cloud Migration Management page and run the Repair Companion Table
Records action to insert the missing table extension records.

Disabling the cloud migration


Database: online

When you've completed the migration, disable cloud migration by using the Disable Cloud Migration action
on the Cloud Migration Management page. This action properly disengages the synchronization and cleans
up the Azure Data Factory resources deployed for this migration.

IMPORTANT
Just uninstalling the cloud migration apps, even with the option to remove the data, won't disable the migration in the
same way. If you don't disable Cloud Migration , users will experience permission-related errors when they try to modify
records in the migrated companies.

See also
Migrating On-Premises Data to Business Central Online
Migrate to Business Central Online from Business Central On-premises
Migrate to Business Central Online from Dynamics GP
Upgrading from Dynamics NAV to Business Central Online
FAQ about Connecting to Business Central Online from On-Premises Solutions
Compare Work Processes in Dynamics GP to
Business Central
2/6/2023 • 2 minutes to read • Edit Online

Moving to Business Central from Dynamics GP can seem daunting, even for experienced users. To help people
quickly become productive, we're producing videos that demystify the experience by explaining the differences
and similarities in work processes.

TIP
The videos in this article probably seem a little small. To get a closer look, switch the video player to full screen view.

Enter receivables transactions


This video compares the process of entering receivables transactions in Dynamics GP and Business Central.

Pay vendors
This video compares the process of paying vendors in Dynamics GP and Business Central.

Enter payables transactions


This video compares the process of entering payables transactions in Dynamics GP and Business Central.

Enter customer cash receipts


This video compares the process of entering customer cash receipts in Dynamics GP and Business Central.

Set up segments and dimensions


This video compares the process of setting up segments and dimensions in Dynamics GP and Business Central.
Create dimension transactions and reports
This video compares the process of creating transactions for dimensions and using them in reports in Dynamics
GP and Business Central.

Use classes and templates


This video compares the process of setting up classes and templates in Dynamics GP and Business Central.

Use general journal entries


This video compares the process of using general journals in Dynamics GP and Business Central.

Correct and reverse entries


This video compares the process of correcting and reversing entries in Dynamics GP and Business Central.

Run trial balance and aging reports


This video compares the process of running trial balance and aging reports in Dynamics GP and Business
Central.

Use posting accounts


This video compares the process of using posting accounts in Dynamics GP and Business Central.
See also
Migrate Dynamics GP Data to the Cloud
Migrate On-Premises Data to Business Central Online
Dynamics GP docs
Development in AL
2/6/2023 • 4 minutes to read • Edit Online

Extensions are a programming model where functionality is defined as an addition to existing objects and
defines how they're different or modify the behavior of the solution. This section explains how you can develop
extensions using the development environment for Dynamics 365 Business Central.
If you're new to building extensions, we recommend that you read this document to get an understanding of the
basics and terms you'll encounter while working. Next, follow the Get Started with AL to set up the tools.

TIP
If you are looking for the C/SIDE documentation, visit our Dynamics NAV library.

Understanding objects in the development environment


All functionality in Business Central is coded in objects. The extension model is object-based; you create new
objects, and extend existing objects depending on what you want your extension to do.
Table objects define the table schema that holds data.
Page objects represent the pages seen in the user interface.
Codeunits contain code for logical calculations and for the application behavior.
These objects are stored as code, known as AL code, and are saved in files with the .al file extension. The AL
Language extension also supports the multi-root functionality, which allows you to work with multiple AL
folders within one workspace. For more information on how to group a set of disparate project folders into one
workspace, see Working with multiple AL project folders within one workspace.

NOTE
A single .al file may contain multiple objects.

Table extension objects and page extension objects are used to add or override changes to table or page objects.
For example, consider a business that sells organic food, and the business wants to add two extra fields;
Organic and Local Produce in its existing item table. The business will use a table extension object to define
those extra fields. The table extension has made the newly added fields available for use in the item table. You
can store data in these fields and access them by code. You can then use the page extension object to display the
fields in the UI.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

You have several options for creating new objects with the AL Language extension for Visual Studio Code. For
more information about the objects that you can create for your extension, see AL Development Environment.

Developing extensions in Visual Studio Code


Using the AL Language extension for Visual Studio Code, you'll get the benefits of a modern development
environment along with seamless publishing and integration with your Business Central tenant. For more
information on the setup, see Get Started with AL.
Visual Studio Code and the AL Language extension let you do the following tasks:
Create new files for your solution.
Assists you with the creation of appropriate settings and configuration files.
Provides code snippets to help create application objects.
Gives compiler validation while you code.
Provides efficient publishing process. You can publish and see your code running by just pressing Ctrl+F5 .

NOTE
For some users the Ctrl+F5 shortcut key may not work due to keyboard or other settings. If it doesn't work for you, run
your code by choosing Run Without Debugging from the Run menu in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

NOTE
If you have previous experience working with the C/SIDE development environment and need an overview of some of the
changes between the two development environments, see Differences in the Development Environments.

Designer
Designer works in the client and allows you to design pages using drag and drop components. Designer lets you
build extensions in the client itself by rearranging fields, adding fields, and previewing your changes in page
design. For more information, see Using Designer.

Compiling and deploying


Extensions are compiled as .app package files. The .app package file can be deployed to the Business Central
server. A .app package contains the various artifacts that deliver the new functionality to the Business Central
deployment and a manifest that specifies the name, publisher, version, and other attributes of the extension. For
information about the manifest files, see JSON Files.

Instrumenting your app with telemetry


Business Central emits telemetry data for several operations that occur when extension code is run. You can
configure your extension to send this data to a specific Application Insights resource on Microsoft Azure. For
more information, see Sending Extension Telemetry to Azure Application Insights.

Submitting your app


After development and testing are done, you can submit your extension package to AppSource. Before you
submit the extension package, we encourage you to read the checklist to facilitate the validation process. For
more information, see Checklist for Submitting Your App. To get code validation helping you to bring your
extension package to AppSource, you can enable the AppSourceCop code analyzer. For more information, see
Using the Code Analysis Tool.
See Also
Get Started with AL
Getting Started Developing Connect Apps for Dynamics 365 Business Central
Keyboard Shortcuts
AL Development Environment
XML Comments in Code
FAQ for Developing in AL
Sending Extension Telemetry to Azure Application Insights
Get Started with AL
2/6/2023 • 4 minutes to read • Edit Online

To start writing extensions for Dynamics 365 Business Central, you'll need a Business Central tenant, Visual
Studio Code, and the AL Language extension. Visual Studio Code is a cross-platform editor that you'll use for
coding and debugging.

Steps to set up a sandbox environment and Visual Studio Code


Go through the following steps to set up a sandbox environment. Having set up a sandbox environment, you get
sample code that compiles and runs with just a few commands.

NOTE
If you want to create a container-based sandbox, see Get started with the Container Sandbox Development Environment.
For information about which sandboxes you can choose, see Sandbox Environments for Dynamics 365 Business Central
Development.

IMPORTANT
It is not supported to publish an extension from Visual Studio Code with the same identifiers as an extension which is
already published to AppSource. Identifiers include the combination of appID and version or name, publisher, and version.
If you do publish such an extension, it can be removed at any time.

1. Sign up for a Dynamics 365 Business Central sandbox.


2. Download Visual Studio Code.
3. Download the AL Language extension.
4. Press Ctrl+Shift+P to open the User Settings window; here you can modify the telemetry settings.
5. Press Alt+A , and right after, Alt+L to trigger the AL Go! command, choose a path to a new empty folder
and which version to run. Then choose Microsoft cloud sandbox as the server.

NOTE
If you want to change your configuration at a later point in time, you can choose the Add Configuration button
on the bottom right side, and then choose one of the available options.

6. Enter the credentials that you provided for the sign-up.


7. Press Ctrl+F5 to deploy and run the extension on your online sandbox tenant.

NOTE
For some users the Ctrl+F5 shortcut key may not work due to keyboard or other settings. If it doesn't work for you, run
your code by choosing Run Without Debugging from the Run dropdown in Visual Studio Code.

You now have a HelloWorld sample that compiles and runs. The JSON files in the project are automatically
updated with the settings that allows you to press Ctrl+F5 to build and deploy the solution to Business Central.
For more information, see JSON Files.
Tips and tricks
Use Ctrl+Space to activate IntelliSense at any place in the code, which will help you identify possible
options.
Always use the .al extension on new files.
Use the built-in snippets for code by typing t and choose the desired snippet from the list.
Create objects within the right object ranges, see Object Ranges in Dynamics 365 Business Central.
Build and get inspired by our sample library on GitHub.
Use Ctrl+Shift+P and select AL: Clear credentials cache to clear the credentials cache if you want to
deploy against a different environment.
Use F2 to rename objects, types etc. For more information, see Keyboard Shortcuts.

JSON file settings


There are three JSON files in the project; the app.json file, the launch.json file, and the rad.json . The files are
automatically generated for your project. For more information, see JSON files and Work with Rapid Application
Development (RAD).

AL configuration settings
Use the AL configuration settings to specify general preferences for working with AL projects. For more
information, see AL Language Extension Configuration.

Telemetry settings
By default, Visual Studio Code is set up with a telemetry system to make sure that data and errors are sent to
Microsoft. If you don't want to send telemetry data, you can change the telemetry.enableTelemetry setting from
true to false .

To modify the telemetry setting, press Ctrl+Shift+P in Visual Studio Code and choose User Settings , which
opens the settings.json file, and then add telemetry.enableTelemetry and set it to false like shown below.

"telemetry.enableTelemetry": false,

TIP
The settings.json file contains user and workspace settings, these options can be modified to suit your preference. If
you want to modify Visual Studio Code editor options and functional behavior settings, see User and Workspace Settings.

Installing and publishing an extension


To make your extension available to users, the package must be published to a specific Business Central server
instance. The extension can be installed for one or more tenants. For more information about how to install and
publish an extension, see How to: Publish and Install an Extension.

Controlling user access to develop and publish extensions


The access to develop and publish extensions is controlled on a user or user group basis by the EXTEND. MGT.
- ADMIN permission set. It's important that the EXTEND. MGT. - ADMIN isn't specified for a specific company,
but left blank.
If you add new permission sets and want to control the access to develop and publish extensions, you must
include indirect read and write permissions to the Published Application table (read – for downloading
symbols, write – for publishing the app) in the permission set.
To prohibit a user from publishing, just remove the user from the EXTEND. MGT. - ADMIN permission set.

NOTE
The EXTEND. MGT. - ADMIN permission set was introduced in Business Central 2021 release wave 1 as a replacement
for the D365 EXTENSION MGT permission set in earlier versions.

Next steps
Now that you have the tools and the HelloWorld example up and running, you might want to create a small
sample app in AL. This walkthrough guides you to create an app adding objects, code, and publishing the app to
your tenant. For more information, see Building Your First Sample Extension With Extension Objects, Install
Code, and Upgrade Code.

See Also
AL Development Environment
FAQ for Developing in AL
Syntax
Building Your First Sample Extension With Extension Objects, Install Code, and Upgrade Code
AL Language Extension Configuration
XML Comments in Code
Building your first Sample Extension with Extension
Objects, Install Code, and Upgrade Code
2/6/2023 • 16 minutes to read • Edit Online

This walkthrough will guide you step by step to create a sample extension in AL. New objects and extension
objects will be added to the base application for a simple reward feature for customers. Every section of this
exercise includes code that serves for installing, customizing, or upgrading this sample extension. The final result
can be published and installed on your tenants.

About this walkthrough


This walkthrough covers the following tasks:
Developing a sample extension with a table, a card page, and a list page.
Deploying the sample extension to your development sandbox environment.
Using the Dynamics 365 Business Central Designer to modify visual aspects of the extension.
Creating extension objects that can be used to modify page and table objects.
Initializing the database during the installation of the extension.
Upgrading and preserving data during the upgrade of the extension.

Prerequisites
To complete this walkthrough, you'll need:
The Dynamics 365 Business Central tenant.
Visual Studio Code.
The AL Language extension for Visual Studio Code.
For more information on how to get started with your first extension for Dynamics 365 Business Central, see
Getting Started.

Rewards extension overview


This extension enables the ability to assign one of the three reward levels to customers: GOLD, SILVER, and
BRONZE. Each reward level can be assigned a discount percentage. Different types of objects available within
the AL development environment will build the foundation of the user interface, allowing the user to edit the
information. If you look for another option to update the layout of a page, you can use the Designer drag-and-
drop interface. Additionally, this exercise contains the install code that will create the base for the reward levels.
The upgrade code is run to upgrade the extension to a newer version and it will change the BRONZE level to
ALUMINUM. By following all the steps of this walkthrough, you can publish the extension on your tenant and
create a possible new feature for your customers.

Reward table object


The following code adds a new table 50100 Reward for storing the reward levels for customers. The table
consists of three fields: Reward ID , Description , and Discount Percentage . For example, the Description
field must contain a value of type text and it can't exceed the limit of 250 characters. The second field contains
three properties that are used to set the range of the discount percentage assigned to every customer.
Properties can be created for every field, depending on the scope.

TIP
Type ttable followed by the Tab key. This snippet will create a basic layout for a table object.

table 50100 Reward


{
DataClassification = ToBeClassified;

fields
{
// The "Reward ID" field represents the unique identifier
// of the reward and can contain up to 30 Code characters.
field(1;"Reward ID";Code[30])
{
DataClassification = ToBeClassified;
}

// The "Description" field can contain a string


// with up to 250 characters.
field(2;Description;Text[250])
{
// This property specified that
// this field cannot be left empty.
NotBlank = true;
}

// The "Discount Percentage" field is a Decimal numeric value


// that represents the discount that will
// be applied for this reward.
field(3;"Discount Percentage";Decimal)
{
// The "MinValue" property sets the minimum value for the "Discount Percentage"
// field.
MinValue = 0;

// The "MaxValue" property sets the maximum value for the "Discount Percentage"
// field.
MaxValue = 100;

// The "DecimalPlaces" property is set to 2 to display discount values with


// exactly 2 decimals.
DecimalPlaces = 2;
}
}

keys
{
// The field "Reward ID" is used as the primary key of this table.
key(PK;"Reward ID")
{
// Create a clustered index from this key.
Clustered = true;
}
}
}

For more information about table properties, see Table Properties.


Reward card page object
The following code adds a new page 50101 Reward Card for viewing and editing the different reward levels
that are stored in the new Reward table. Pages are the primary object that a user will interact with and have a
different behavior based on the type of page that you choose. The Reward Card page is of type Card and it's
used to view and edit one record or entity from the Reward table.

TIP
Use the snippet tpage, Page to create the basic structure for the page object.

page 50101 "Reward Card"


{
// The page will be of type "Card" and will render as a card.
PageType = Card;

// The page will be part of the "Tasks" group of search results.


UsageCategory = Tasks;

// The source table shows data from the "Reward" table.


SourceTable = Reward;

// The layout describes the visual parts on the page.


layout
{
area(content)
{
group(Reward)
{
field("Reward Id"; Rec."Reward ID")
{
// ApplicationArea sets the application area that
// applies to the page field and action controls.
// Setting the property to All means that the control
// will always appear in the user interface.
ApplicationArea = All;
}

field(Description; Rec.Description)
{
ApplicationArea = All;
}

field("Discount Percentage"; Rec."Discount Percentage")


{
ApplicationArea = All;
}
}
}
}
}

For more information about the types of pages in AL, see Pages Overview.

Reward list page object


The following code adds the 50102 Reward List page that enables users to view the contents of the Reward
table and edit specific records by selecting them and viewing them in the Reward Card page.
TIP
Use the snippet tpage, Page of type list to create the basic structure for the page object.

page 50102 "Reward List"


{
// Specify that this page will be a list page.
PageType = List;

// The page will be part of the "Lists" group of search results.


UsageCategory = Lists;

// The data of this page is taken from the "Reward" table.


SourceTable = Reward;

// The "CardPageId" is set to the Reward Card previously created.


// This will allow users to open records from the list in the "Reward Card" page.
CardPageId = "Reward Card";

layout
{
area(content)
{
repeater(Rewards)
{
field("Reward ID"; Rec."Reward ID")
{
ApplicationArea = All;
ToolTip = 'Specifies the level of reward that the customer has at this point.';
}

field(Description; Rec.Description)
{
ApplicationArea = All;
}

field("Discount Percentage"; Rec."Discount Percentage")


{
ApplicationArea = All;
}
}
}
}
}

After you've created the objects, update the startupObjectId in the launch.json file to 50102 , which is the ID of
the Reward List page and select the Ctrl+F5 shortcut to see the new page in your sandbox environment. You'll
be asked to sign in to your Business Central, if you haven't already done so.

TIP
Information about your sandbox environment and other environments is stored as configurations in the launch.json
file. For more information, see JSON Files.

Designer
Dynamics 365 Business Central Designer works in the browser and allows modifying the current page. It
enables users to add existing table fields, move fields around, or remove fields from the page. Users can make
changes to display the information they need, where they need it by using drag-and-drop components.
To show how Designer changes the design of a page, you begin by adding one field to the Reward table. This
field will be used later to exemplify the Designer's properties.

field(4;"Minimum Purchase";Decimal)
{
MinValue = 0;
DecimalPlaces = 2;
}

From this point, changes to the Reward Card page can be done either manually by adding the code below in
Visual Studio Code or by using Designer's functions to add the same field. Both ways lead to the same results,
but using Designer speeds up the process.

field("Minimum Purchase";"Minimum Purchase")


{
ApplicationArea = All;
}

Using the F6 key shortcut in Visual Studio Code launches the browser and enters Designer. You can also use
Designer from the Business Central client, by selecting Designer .

NOTE
Every time you start designing, you create a new extension and the changes you make in Designer will apply to all users.

To add the same fields and customize the Reward Card page, follow the next steps:
Navigate to the Reward Card page by choosing + new .
Enter Designer mode from the UI and select More from the Designer bar.
Select Field from the Designer bar to show the list of available fields.
Drag the Minimum Purchase field from the list onto the page in the Reward group .
Choose the Reward in the group caption to enable the value to be edited. Change the caption to Info and
press Enter .
After making these adjustments, finish up your design by choosing Stop Designing , which allows you to name
the extension with an option to download code, and save the extension for the tenant. If you choose not to
download the code at the end, you can still pull the changes via the Alt+F6 key shortcut from Visual Studio
Code. You can also uninstall the extension from the Extension Management page. You can find the Extension
Management page by choosing the search icon and typing the page name.
For more information about Designer, see Designer.

Customer table extension object


The Customer table, like many other tables, is part of the Dynamics 365 Business Central's core service and it
can't be modified directly by developers. To add new fields or to change properties on this table, developers
must create a new type of object by using a table extension.
The following code creates a table extension for the Customer table and adds the Reward ID field.

TIP
Use the snippet ttableext to create a basic structure for the table extension object.
tableextension 50103 "Customer Ext" extends Customer
{
fields
{
field(50100;"Reward ID";Code[30])
{
// Set links to the "Reward ID" from the Reward table.
TableRelation = Reward."Reward ID";

// Set whether to validate a table relationship.


ValidateTableRelation = true;

// "OnValidate" trigger executes when data is entered in a field.


trigger OnValidate();
begin

// If the "Reward ID" changed and the new record is blocked, an error is thrown.
if (Rec."Reward ID" <> xRec."Reward ID") and
(Rec.Blocked <> Blocked::" ") then
begin
Error('Cannot update the rewards status of a blocked customer.')
end;
end;
}
}
}

NOTE
While running the code, you might get errors and warnings in Visual Studio Code. Those errors and warnings shouldn't
affect the output of this example exercise.

Customer card page extension object


A page extension object can be used to add new functionality to pages that are part of the Dynamics 365
Business Central's core service. The following page extension object extends the Customer Card page object
by adding a field control, Reward ID , to the General group on the page. The field is added in the layout
section, while in the related section, find Related by extending the three dots icon, the code adds an action
Rewards to open the Reward List page.

TIP
Use the shortcuts tpageext to create the basic structure for the page extension object.
pageextension 50104 "Customer Card Ext" extends "Customer Card"
{
layout
{
// The "addlast" construct adds the field control as the last control in the General
// group.
addlast(General)
{
field("Reward ID"; Rec."Reward ID")
{
ApplicationArea = All;

// Lookup property is used to provide a lookup window for


// a text box. It is set to true, because a lookup for
// the field is needed.
Lookup = true;
}
}
}

actions
{
// The "addfirst" construct will add the action as the first action
// in the Navigation group.
addfirst(Navigation)
{
action("Rewards")
{
ApplicationArea = All;

// "RunObject" sets the "Reward List" page as the object


// that will run when the action is activated.
RunObject = page "Reward List";
}
}
}
}

At this point, reward levels can be created and assigned to customers. To view recent changes in the code,
update the startupObjectId value in the launch.json file to 21 . Then, select the Ctrl+F5 key or Run Without
Debugging from the Run menu to open the page.

Help links
This sample app is relatively straightforward, but we want users of your app to be able to get help instantly and
learn more in the process of using it. Just like Business Central has Help readily available for users, you'll
configure your app to get context-sensitive links to Help, and then apply tooltips to the fields in your pages.
Configure context-sensitive links to Help
At an app level, you can specify where the Help for your functionality is published in the app.json file. Then, for
each page in your app, you specify a relevant Help file on your targeted website for that particular page. For
more information, see Configure Context-Sensitive Help.
Open the app.json file, and then change the value of the contextSensitiveHelpUrl property to point at the right
location on your website. In this example, you publish Help for your app at https://mysite.com/documentation .

"contextSensitiveHelpUrl": "https://mysite.com/documentation/",

Next, you set the ContextSensitiveHelpPage property in your app code for the Reward Card and Reward List
pages:
// The target Help topic is hosted on the website that is specified in the app.json file.
ContextSensitiveHelpPage = 'sales-rewards';

The following example shows the properties for the Reward List page after you've specified the context-
sensitive Help page.

page 50102 "Reward List"


{
// Specify that this page will be a list page.
PageType = List;

// The page will be part of the "Lists" group of search results.


UsageCategory = Lists;

// The target Help topic is hosted on the website that is specified in the app.json file.
ContextSensitiveHelpPage = 'sales-rewards';

// The data of this page is taken from the "Reward" table.


SourceTable = Reward;

// The "CardPageId" is set to the Reward Card previously created.


// This will allow users to open records from the list in the "Reward Card" page.
CardPageId = "Reward Card";

...

Now, if you run your app, you can see the link to help article for Reward List page by pointing over Reward ID
and choosing Learn More . The URL of your targeted website is present in the Help section. You can specify the
same relative link for Reward Card , Reward List , and the customization of the Customer page, or you can
specify different targets. For more information, see Page-level configuration.
Add tooltips
To help users navigate the app interface without any confusion and to add more clarity on the app features, you
can use tooltips. Just like the base application of Dynamics 365 Business Central includes tooltips for all controls
and actions. For more information, see Help users get unblocked.
For this walkthrough, add the following tooltip to the properties of the Reward ID field on all three pages,
Reward Card, Reward List, and Customer Card ext:

ToolTip = 'Specifies the level of reward that the customer has at this point.';

The following example shows the tooltip:

field("Reward ID";"Reward ID")


{
ApplicationArea = All;
ToolTip = 'Specifies the level of reward that the customer has at this point.';
}

Now, if you deploy the app, you'll be able to read the tooltip text for the Reward ID field, and if you choose the
Learn more link or press Ctrl+F1 , a new browser tab opens the equivalent of
https://mysite.com/documentation/sales-rewards .
Install code
After you have installed the extension, the Reward List page is empty. This is the result of the fact that the
Reward table is also empty. Data can be entered manually into the Reward table by creating new records from
the Reward List page. However, this task slows down the process, especially because the Reward table should
be initialized with a standard number of reward levels when the extension is installed. To solve this, install
codeunits can be used.
A codeunit is an object that can be used to encapsulate a set of related functionality represented by procedures
and variables. An install codeunit is a codeunit with the Subtype property set to Install. This codeunit provides a
set of triggers that are executed when a particular extension is installed for the first time or when it's reinstalled.
In this example, the following install codeunit initializes the Reward table with three records representing the
'GOLD', 'SILVER', and 'BRONZE' reward levels.

TIP
Use the shortcuts tcodeunit to create the basic structure for the codeunit.
codeunit 50105 RewardsInstallCode
{
// Set the codeunit to be an install codeunit.
Subtype = Install;

// This trigger includes code for company-related operations.


trigger OnInstallAppPerCompany();
var
Reward : Record Reward;
begin
// If the "Reward" table is empty, insert the default rewards.
if Reward.IsEmpty() then begin
InsertDefaultRewards();
end;
end;

// Insert the GOLD, SILVER, BRONZE reward levels


procedure InsertDefaultRewards();
begin
InsertRewardLevel('GOLD', 'Gold Level', 20);
InsertRewardLevel('SILVER', 'Silver Level', 10);
InsertRewardLevel('BRONZE', 'Bronze Level', 5);
end;

// Create and insert a reward level in the "Reward" table.


procedure InsertRewardLevel(ID : Code[30]; Description : Text[250]; Discount : Decimal);
var
Reward : Record Reward;
begin
Reward.Init();
Reward."Reward ID" := ID;
Reward.Description := Description;
Reward."Discount Percentage" := Discount;
Reward.Insert();
end;

For more information about install code, see Writing Extension Install Code.

Upgrade code
When you upgrade an extension to a newer version, any modifications, which are required to support the
upgrade in the existing data must be written in an upgrade codeunit. In this example, the following upgrade
codeunit contains code that changes the BRONZE reward level to ALUMINUM level in customer records. The
upgrade codeunit will apply the changes when you run the Start-NAVAppDataUpgrade cmdlet in terminal.

IMPORTANT
Remember to increase the version number of the extension in the app.json file.
codeunit 50106 RewardsUpgradeCode
{
// An upgrade codeunit includes AL methods for synchronizing changes to a table definition
// in an application with the business data table in SQL Server and migrating existing
// data.
Subtype = Upgrade;

// "OnUpgradePerCompany" trigger is used to perform the actual upgrade.


trigger OnUpgradePerCompany();
var
Reward : Record Reward;

// "ModuleInfo" is the current executing module.


Module : ModuleInfo;
begin
// Get information about the current module.
NavApp.GetCurrentModuleInfo(Module);

// If the code needs to be upgraded, the BRONZE reward level will be changed into the
// ALUMINUM reward level.
if Module.DataVersion.Major = 1 then begin
Reward.Get('BRONZE');
Reward.Rename('ALUMINUM');
Reward.Description := 'Aluminum Level';
Reward.Modify();
end;
end;
}

For more information about writing and running upgrade code, see Upgrading Extension.

Instrumenting your app with telemetry


Business Central emits telemetry data for several operations that occur when extension code is run. Create an
Application Insights resource in Azure if you don't have one. For more information, see Create an Application
Insights resource. Now, add the Application Insights connection string to the extension manifest (app.json file):

"applicationInsightConnectionString":"<connection string>"

Replace <connection string> with your connection string.


You can configure your extension to send this data to a specific Application Insights resource on Microsoft Azure.
For more information, see Sending Extension Telemetry to Azure Application Insights.

Conclusion
This walkthrough showed how an extension can be developed. The main AL objects and extension objects were
used to make a structure for reward levels, to store, view, and edit them. The Designer was introduced as an
alternative to modify visual components of page objects and to customize them directly from the web interface
instead of using code. Up to this point, the table and the page objects were empty, so, we added install codeunit
which initialized the Reward table with a standard number of reward levels when the extension was installed.
We also added an upgrade code section in this exercise to create a complete picture of all processes involved
when an extension is built. As a result, a user is enabled to assign one of the three reward levels to a customer
and to change this scenario by upgrading the version of the extension.
TIP
To try building a more advanced Customer Rewards sample extension, see Building an Advanced Sample Extension.

See Also
Developing Extensions
Get Started with AL
How to: Publish and Install an Extension
Converting Extensions V1 to Extensions V2
Configure Context-Sensitive Help
Sending Extension Telemetry to Azure Application Insights
Using Designer
2/6/2023 • 10 minutes to read • Edit Online

When developing extensions in the AL development environment, you have a wide range of possibilities.
Designer in Dynamics 365 Business Central complements the development experience in Visual Studio Code. It
provides an easy and convenient way to make immediate changes to your design by dragging and dropping the
components on the page.

IMPORTANT
Currently, Designer is only available from a Dynamics 365 Business Central sandbox.
Every time you start designing, you're effectively creating a new extension. Your changes are immediately visible to other
users in the sandbox environment.
Designer cannot be used by multiple users at the same time in sandboxes.

NOTE
Extensions created using Designer are removed when the sandbox environment is updated or relocated within our
service. Thus, you should not rely on using the sandbox environment as a source control for these Designer extensions.
Remember to frequently download and backup the Designer extension source. For more information, see Production and
Sandbox Environments.

Designer capabilities
Here's a quick overview of capabilities in Designer :

F EAT URES A P P L IES TO

Add components fields, columns, parts, actions in navigation bar

Move components fields, columns, cues, parts, actions, and action groups

Remove components fields, columns, cues, parts, actions, and action groups

Hide and unhide components parts

Change field importance, like showing in collapsed FastTab fields


header or under Show More

Exclude field from Quick Entry fields, columns

Set freeze pane and clear freeze pane columns

Adjust column width columns

Edit caption FastTabs, cards, FactBoxes

Save extension/download code general


F EAT URES A P P L IES TO

Preview design general

Important points to note


Every time you start designing, you're effectively creating a new extension. Your changes are immediately
visible to other users in the sandbox environment.
The changes you make in Designer will apply to all users.
You can't remove specific fields that are bound to a page and a field must belong to an underlying table.
You can only add fields, columns, or tiles to its applicable view from list, tall tiles, and wide tiles views. Some
components can't be moved using drag-and-drop and are restricted to the view that they are in.
You can only add fields/columns, from a predefined list, which is based on the source table. You can't create
new ones.
In the client, users can change many of these settings for their workspace by using personalization. For more
information, see Personalizing Your Workspace.

Start and stop designing


In the Business Central client, you start Designer by choosing icon and then Design in the top-right corner
of any page and start designing using drag-and-drop components. In Visual Studio Code, you can start Designer
by using the F6 shortcut key, which launches a browser that opens the Business Central client in Designer.
After you're done with the changes, choose Stop Designing . You can name the extension and download code
to save it for the tenant. Once you're done, the extension is automatically installed. If you choose to download
the code, the project will be downloaded as a .zip folder. You extract the files and open the folder from Visual
Studio Code, where you can deploy it as you would do with any other extension.
If you choose not to download the code at the end, you can still pull the code using the Alt+F6 shortcut. You can
also uninstall the extension from the Extension Management page or even download the source from there.
You can find Extension Management page by choosing the search icon and typing the page name.

Drag-and-drop components
In Designer, you design and modify the current page by using drag and drop components. You can display
existing table fields, move fields around, remove fields from the page, hide and move actions, and much more.
Working with fields
To add a field or column to a page, in the banner, choose Field . A pane to the right appears that lets you add
fields. Here, you can see all the fields that are available for the specific page. The fields displayed are based on
the underlying table or tables. The field can have a status of Placed , which means that the field already exists on
the page. A status of Ready means that the field doesn't exists on the page and can be added. To add a field,
drag and drop it to the preferred location.

If you want to remove a field or column, select the arrowhead indicator or on the component, and then
choose Remove .
You can edit the caption of a FastTab (FastTabs divide key information in separate groups and are arranged in
columns) by selecting the caption and start writing. A caption should provide a short and clear description. For
more information, see Field Arrangement on FastTabs

Setting the freeze pane


Set freeze pane locks one or more columns to the left, even when you scroll horizontally. You can set the
freeze pane, by selecting the arrowhead indicator or of the column that you want as the last column of
the freeze pane, and then choose Set Freeze Pane . If you want to set the freeze pane back to its original
designed location, select the arrowhead indicator or for the current freeze pane column, and then choose
Clear Freeze Pane .

Setting the Importance on a field


Fields on non-list type pages, such as card and document type pages, include Designer options for setting the
importance. The following table describes the options for setting the importance in Designer and how it
corresponds to the Importance property in the page code.

O P T IO N DESC RIP T IO N IM P O RTA N C E P RO P ERT Y VA L UE

Show under "Show more" Sets the field so that it appears only Additional
when the user selects Show more .

Show always Sets the field to always display on the Standard


page. The field is displayed regardless
the user selects Show more or Show
less . The field won't show in the
FastTab heading if the FastTab is
collapsed.

Show when collapsed Sets the field to always display on the Promoted
page. The field is displayed regardless
the user selects Show more or Show
less . The fields will also display in the
header of the FastTab if the FastTab is
collapsed.

Setting the Quick Entry on fields


You can use Designer to set the QuickEntry property on a field. The QuickEntr y property determines whether
the field is skipped when users press the Enter key to navigate through fields on a page. You use Quick Entry to
speed up the data entry by keyboard and to focus only on the frequently used fields.
To set the QuickEntry property from Designer, select the field or column heading, and then choose either
Include in Quick Entr y (sets the QuickEntr y property to true ) or Exclude from Quick Entr y (sets the
QuickEntr y property to false ).
For more information about QuickEntry property, from a user perspective, see Accelerating Data Entry Using
Quick Entry in the Business Central Application Help.

Working with the Navigation menu and Navigation bar


Designer lets you add actions that link to pages and reports in the navigation bar using the bookmark icon on
the target page or report. The bookmark icon is also available in the Tell Me window.

NOTE
Bookmarking is only available for pages and reports that are discoverable from Tell Me (search icon on top right). For
more information on how to make pages and reports searchable, see Adding Pages and Reports to Tell me.

This feature allows the user to efficiently create multiple links and group together the important or commonly
used links for a specific profile in the Role Center navigation bar. For more information about bookmarking, see
Bookmark a Link to a Page or Report on Your Role Center in the Business Central Application Help.
You can also move actions to reorder them in the navigation bar, or move them into groups or subgroups to
design the Navigation Menu.

Hiding and showing Parts


Designer lets you hide and unhide part controls in a page directly from the client. When you select the Hide
option on a part, it will be grayed-out and disappear from the page when you quit Designer mode. Similarly, you
can select Show on a grayed part control to make it visible again to the user.
The extension generated when the user hides or shows a part overrides the Visible Property in code. For more
information on how the Visible Proper ty affects the visibility of a control, see UI Customization and Visibility
of Controls.

Working with Actions


Designer lets you make changes to the actions that are defined in the action bar of a page. You can move,
remove, hide, and show individual actions or action groups.

NOTE
You cannot modify actions that are defined on pages that are shown in parts, such as in FactBoxes or embedded lists.
TIP
In Designer, to run an action as normal, select the action and press Ctrl+Click .

Remove, hide, and show actions and groups


Actions and actions groups that are already hidden appear dimmed. To change the state of an action or action
group, select it, and then choose one of the following options:

O P T IO N W H AT IT DO ES

Remove This option is available for the actions that are shown only in
a promoted category. Or actions that are shown in both,
promoted category and another action menu.

Choosing Remove deletes the action from the selected


location so that it no longer appears.

If the action is only shown in the promoted category, it will


automatically be shown in the action menu where it's
originally defined.

You can't remove actions on a Role Center page; you can


only hide them.

Hide This option is available for actions or action groups that are
currently shown only in an action menu (not in a promoted
category). Like Remove , choosing Hide will make the action
or action group disappear from the action bar in the client.
However, in Designer, the action or action group appears
dimmed.

Show This option appears if the action or action group has been
previously hidden (dimmed). Choosing this option will make
the action or action group appear in the action bar.

Move actions and action groups


Designer lets you move actions within the action bar. For example, you can:
Move an action from an action menu to a promoted category.
Move an action from one promoted category to another.
Move an action within an action group or to a different action group.
To move an action or action group, drag and drop it to the wanted location, just like with fields and columns.
You can move individual actions into the promoted categories, but you can't change the order of the actions
in the category.
You can't move an action group into a promoted category.
To move an action or action group into an empty action group, drag the action or action group to the target
group and drop it in the Drop an action here box.
On Role Center pages, you can't move actions among the different areas that are defined by the
area(creation) , area(processing) , and area(reporting) controls.

Preview design on different display targets


The display type icons let you preview the changes you made on desktop, tablet, and phone clients. This way you
can make sure that your design will work on the intended display target(s). You can flip to display tablet and
phone designs in portrait and landscape orientation.

Controlling user access to Designer


Accessing Designer is controlled on a user or user group basis by the EXTEND. MGT. - ADMIN permission set.
If a user is assigned this permission set, then Designer is available for the user in the client. To prohibit a user
from using Designer, just remove the user from the EXTEND. MGT. - ADMIN permission set.

NOTE
It is important that the EXTEND. MGT. - ADMIN permission set does not have a company specified; otherwise the user
will not be able to access Designer.

NOTE
The EXTEND. MGT. - ADMIN permission set was introduced in Business Central 2021 release wave 1 as a replacement
for the D365 EXTENSION MGT permission set in earlier versions.

Other things to know


Power Automate item in action bar
You can't hide or move the Automate item or the Power Automate subitem and its actions Create
a flow or Manage Flows .
You can move flows included under the Automate item, but you can't hide them. Moving the flow
makes a copy of the flow to the destination, it won't remove it from the Automate item. Your flow in
Power Automate isn't duplicated.
If the action is moved to the repository area of the action bar (right side of |), a new action is
created at the drop location.
If the action is moved to the promoted area (left side of |) a new actionref is created at the
drop location. This actionref points to a new base action that's appended to the Actions
menu ( Processing action area).

TIP
You can hide the Automation item from users, but not using designer. Learn more at Set Up Power Automate
Integration.

See Also
Developing Extensions
Get Started with AL
AL Development Environment
Keyboard Shortcuts
2/6/2023 • 2 minutes to read • Edit Online

The following table provides an overview of some of the shortcut key combinations that you can use when you
are working in Visual Studio Code. For a complete overview, see Key Bindings for Visual Studio Code.

General in Visual Studio Code


K EY B O A RD SH O RTC UT A C T IO N

Ctrl+Shift+P Show All Commands

Alt+F6 Download source code

Alt+A Alt+L AL Go! Generates a HelloWorld project

Ctrl+Shift+B Package

F5 Publish

Ctrl+F5 Build and publish without debugging. Note: The keyboard


shortcut has a different meaning when debugging.

F6 Publish and open Designer

Ctrl+F2 Update the compiler used by the service tier(s)

Editing in Visual Studio Code


K EY B O A RD SH O RTC UT A C T IO N

Ctrl+Space Look up suggestions for the current object

Ctrl+X Cut

Ctrl+C Copy

Ctrl+V Paste

Ctrl+F2 Select all occurrences

F12 Go to definition

Alt+F12 Peek definition

Shift+F12 Show references

Ctrl+Shift+Space Look up parameter hints


K EY B O A RD SH O RTC UT A C T IO N

Ctrl+K Ctrl+C Add line comment

Ctrl+K Ctrl+U Remove line comment

Ctrl+Shift+P Show all commands

F2 Rename (use Enter to rename, use Shift+Enter to preview)

Shift+Alt+E Look up events and insert event subscriber in code for a


selected event.

Errors in Visual Studio Code


K EY B O A RD SH O RTC UT A C T IO N

F8 Move to the next error or warning

Shift+F8 Move to the previous error or warning

Compile and publish in Visual Studio Code


K EY B O A RD SH O RTC UT A C T IO N

Ctrl+Shift+B Compile and build the solution

Ctrl+F5 Build and deploy

Shift+Alt+W Publish full dependency tree for the active project

Debugging in Visual Studio Code


For topics on debugging in AL, see Debugging and Snapshot Debugging.

K EY B O A RD SH O RTC UT A C T IO N

F5 Start debugging session

Ctrl+F5 Publish without building. Note: The keyboard shortcut has a


different meaning when not debugging.

Ctrl+Alt+F5 Start RAD publishing without debugging

Alt+F5 Start RAD with debugging

F7 Start a snapshot debugging session

Shift+F7 List all available snapshots

Alt+F7 Finish a snapshot debugging session


Profiling in Visual Studio Code
For more information about profiling, see AL Profiler Overview

K EY B O A RD SH O RTC UT A C T IO N

Enter+Toggle Expand and collapse a node.

Arrow+Left Collapse a node.

Arrow+Right Expand a node.

- (minus) Collapse all nodes.

* (star) Expand one level for all nodes. Consecutive keystrokes will
expand to the next level.

See Also
Developing Extensions
Get Started with AL
AL Development Environment
The AL Formatter
2/6/2023 • 2 minutes to read • Edit Online

The AL Language extension offers users the option to automatically format their source code. This capability
increases the usability of the editor by allowing developers to instantly fix the indentation and formatting of
their code. The auto-formatter analyzes the syntax tree of the AL code that you're formatting. By using rules that
are based on the coding and style guidelines for AL, the auto-formatter then inserts and removes whitespace
from key points in the document to make it more readable.

NOTE
The rules used by the auto-formatter cannot be configured by the user. This limitation is present to allow for a uniform
style to be used throughout the community of AL developers.

Invoking the AL formatter


The auto-formatter can be invoked to format an entire AL document or a pre-selected range. In an existing
project, open the document that you want to format, right-click inside the document, and select Format
Document . In the default configuration for Visual Studio Code, the command can be run using the shortcut
Alt+Shift+F .

To format a range, in an already opened project, open the document that you want to modify, select the specific
range to format, right-click, and select Format Selection . In the default configuration for Visual Studio Code,
the command can be run using the shortcut Ctrl+K , Ctrl+F .
See Also
AL Development Environment
AL Outline View
AL Code Actions
AL Outline View
2/6/2023 • 2 minutes to read • Edit Online

Working with the AL Language extension, you have access to the Outline view. The Outline view is a separate
section in the lower left corner, right under the Explorer view.
The Outline view is enabled by default and shows the symbol tree of the currently active cursor, it also allows
you to filter as you type. Double-clicking on any node makes your cursor jump to the selected definition or
keyword. The Outline view will also display any errors in your project for an easy review.

You manage the look and feel of the Outline view by defining settings that are all enabled by default. To modify
settings, press Ctrl+Shift+P , and then choose Preferences: Open Settings (UI) for workspace settings, or
choose Preferences: Open User Settings for user settings. Under Extensions , and AL Language
extension configuration you'll find the settings that are available for the AL Language extension for the
settings.json file.

outline.icons - Outline elements displayed with icons


outline.problems.enabled - Show errors and warnings on outline elements
outline.problems.badges - Badges displayed for errors and warnings
outline.problems.colors - Colors used for errors and warnings

See Also
AL Development Environment
AL Formatter
AL Code Navigation
2/6/2023 • 2 minutes to read • Edit Online

When you develop an AL extension, you may want to navigate around the source code frequently. To jump
around the code or to access the reference code, you use the Go To Definition feature in Visual Studio Code.

Go To Definition
The Go to Definition feature navigates to the source of a type and opens the result in a new tab. You can use
the F12 shortcut key or right-click and select the Go to Definition feature from the right-click menu. The Go
to Definition opens the source in the .dal format that contains the base application code. For example, the
base application code may contain table metadata and application methods. In the following illustration, the
Address type and the HasAddress type open the Customer.dal file and locate the reference code of those types
by using the Go To Definition feature.

With Go to Definition , you can step into the referenced code and set breakpoints on the external code and
base application code. For more information, see Debugging in AL.
You can always use Go to Definition on Dynamics 365 Business Central code. However, if you want to use it on
other extensions, the extension package that is now referenced, when originally published, must have the
includeSourceInSymbols property set to true . The includeSourceInSymbols property is one of the three options
inside the resourceExposurePolicy property. An example is, that if A is referencing B you can only use the Go To
Definition on types of B, if B, when it was published, had the includeSourceInSymbols flag set to true . For more
information, see Resource Exposure Policy Setting.

Runtime 5.2 and Go to Definition


From runtime 5.2 and onwards, Go to Definition will resolve sources from the downloaded application
dependency. You can navigate from within a symbol source file (.dal) to another symbol source file. For example,
you can use Go to Definition from the Customer source DAL file in the Base App to the Customer List DAL
source also defined in the Base App.
The following conditions still apply:
Go to Definition is forward only. It's due to how Visual Studio Code handles preview documents (DAL
files). There's no backward navigation support for preview files within Visual Studio Code. This means
that if you navigate from your AL file to the Customer DAL source, and from there to the Customer List
DAL source, and you issue a backward navigation (Alt+Left arrow ), you'll get back to the AL file and not
what you would have expected; the Customer DAL source.
Transitive references can only be resolved if the symbol app that defines the reference is a dependency on
the project that contains the entry point for the Go to Definition symbol. For example, assume that you
are in HelloWorld.al and want to Go to Definition on the Car table defined in the Car.app , which is a
dependency on your app. Then navigation will open the CarTable.dal preview file. And assume that from
here you want to Go to Definition on CarDistributor table defined in the CarDistributor.app , which is
a dependency on Car.app , but not a dependency on the HelloWorld.app . In this case, the source code Go
to Definition won't work.
For more information about code navigation in Visual Studio Code, see Code Navigation.

See Also
Developing Extensions in AL
JSON Files
Debugging in AL
AL Code Actions
AL Code Actions
2/6/2023 • 2 minutes to read • Edit Online

CHANGED IN: Business Central 2022 release wave 2

The AL Language extension can help users to fix issues in the code. Code Actions is a Visual Studio Code
feature that provides the user with possible corrective actions right next to an error or warning. If actions are
available, a light bulb appears next to the error or warning. When the user chooses the light bulb (or presses
Ctrl+.), a list of available code actions is presented. A code action can be applied to a single instance or a
broader scope depending on the type of action.
In AL Language extension, these code actions are available in the current version:
Multiple IF to CASE converting code action
Spell check code action
Interface implementer
Make method local
Use parenthesis for method call fix for instance, document, project, or workspace.
Fix explicit with statements
Fix implicit with statements
Fix old report layout and replace with rendering layout section
Fix for AW0013
Convert pages or page extensions to use the actionRef syntax for promoted actions on the action bar. Fix for
instance, document, project, or workspace. For more information, see Code action for actions.

Examples
The spell check code action is triggered on certain syntax errors:

The make method local action is triggered to fix the CodeCop Warning AA0207:
Code actions for promoted actions
Use the code action to convert legacy syntax for promoted actions to the actionref syntax, which is introduced
with Business Central 2022 release wave 2. In-client customizations, user personalization, and profile
configurations are automatically converted into the new syntax, so this is primarily applicable to DEV extensions.
The code action can apply to a single instance, the document, the project, or the workspace.

NOTE
For Designer extensions, use F6 to open Designer , which opens the page where the legacy syntax is used. Choose the
Lock symbol and use Unlock page to automatically convert the legacy syntax for the running code. Pressing Alt+F6 will
bring you back into Visual Studio Code, and show the converted actionref code.

To enable AL Code Actions


1. Open the Command Palette by pressing Ctrl+Shift+P and then open the settings.json file.
2. Enter the setting al.enableCodeActions and set it to true like this "al.enableCodeActions": true
3. Save the settings file. You have now enabled code actions on your project.
Alternatively:
1. Open the Settings Page, Ctrl+, and choose either User Settings or Workspace Settings depending on
which scope you want the code actions to apply to.
2. Navigate to Extensions > AL Language extension configuration .
3. Choose the Enable Code Actions checkbox. You've now enabled code actions on your project.

See Also
AL Development Environment
AL Outline View
AL Formatter
Directives in AL
Object Ranges in Business Central
2/6/2023 • 2 minutes to read • Edit Online

When you develop an app for Business Central online, you must request an object range in terms of licensing.
Development for Business Central is done using Visual Studio Code with the AL Language extension.
There are currently two available ranges that you can request. Both have some characteristics to keep in mind:
RSP Object Range (ID range 1,000,000-69,999,999)
This object range is tied to the RSP Program details.

IMPORTANT
We currently advise new publishers to not request an RSP object range

App Object Range (ID range 70,000,000-74,999,999)


This object range was originally designed just for apps in the Microsoft commercial marketplace to be
used in Business Central online.

IMPORTANT
We currently advise new publishers to request an app object range.

Currently, you can implement apps developed in both the RSP range and the app object range in Business
Central online and on-premises, as well as partner-hosted.
For more information, see Requesting an object range.
The following sections describe the different object ranges that you can find in the base application and
extensions.

0-49,999
This range is assigned to Business Central base app functionality and must not be used in extensions or
customizations.

50,000-99,999
This range is for customizations, and for test purposes. For Business Central online, a partner can develop an
extension tailored to the individual tenant to fit the needs. The partner will develop the extension either by using
a sandbox tenant or by obtaining a Docker image. Once the development is done, the extension can be deployed
to the individual tenant.
Also, use this range as part of training and similar, such as if you're using a sandbox tenant or a build of Business
Central on Docker.

100,000-999,999
The objects in this range are designed when the Microsoft team localizes Business Central for a specific country
or region. These objects can't be used by partners.
1,000,000-69,999,999
This object range is intended for the Registered Solution Program (RSP). The partner can choose to use this
range for developing extensions that can be used in Business Central online or on-premises. When used in
Business Central online, these extensions are obtained as apps from appsource.microsoft.com.

70,000,000-74,999,999
Partners can obtain IDs in this range for extensions for Business Central online. These extensions are obtained as
apps from appsource.microsoft.com.
For more information, see Get Started with Building Apps.
Download the Business Central licensing guide here.

See Also
Get Started with Building Apps
Get Started with AL
Blog Post
Differences in the Development Environments
2/6/2023 • 3 minutes to read • Edit Online

Coming from the Dynamics NAV development environment and C/SIDE, it's good to know about some
differences and optimizations between them. The following sections go through some of these changes, but it
isn't an exhaustive list.

TIP
A very useful tool working in Visual Studio Code is IntelliSense, which gives you a list of options in the current context. To
activate IntelliSense from anywhere in the code, press Ctrl+Space .

General development approach


While you could change the existing Dynamics NAV source code using C/SIDE, the best approach to develop
with the AL Language development environment is to work with Extensions only. It means that you can extend
the existing code by adding new functionality or integrate your code using Events. But, it isn't possible to change
the existing code, for example in codeunits.
With Business Central 2019 release wave 2, the possibility to change or "code-customize" the base application
was introduced for on-premise installations. But, it was also announced that in the future, code-customization
won't be an option, only extension model will be used.

Data types
C / SIDE A L L A N GUA GE DEVELO P M EN T EN VIRO N M EN T

Dates are parsed based on culture settings. Locale independent and supports only: yyyy-mm-ddD .

Boolean values are expressed as yes /no . Boolean values are expressed as true /false .

For tables, integers can allow decimal values. For example, For tables, Min, Max, InitValue numbers with a fraction are
5.0 converts to an integer, 5.4 throws an error at runtime. expressed as decimal , thus they aren't a valid integer data
type.

The largest constant integer can be 999999999999999 . Transforms to 999'999'999'999'999.0 , a decimal value. In
AL, this can be expressed as 999999999999999.0 or
999999999999999L .

Syntax updates
C / SIDE A L L A N GUA GE DEVELO P M EN T EN VIRO N M EN T

The token for multilanguage comment is @@@. A multilanguage comment is marked with Comment .

Several properties are renamed, for example:


C / SIDE A L L A N GUA GE DEVELO P M EN T EN VIRO N M EN T

AutoFormatExpr AutoFormatExpression

DataCaptionExpr DataCaptionExpression

Layout GridLayout

ProviderID Provider

NOTE
Property values are considered syntax elements; thus they must follow the standard AL escaping rules.

Multilanguage properties
With the introduction of .xliff files, the ML properties, such as CaptionML and TooltipML aren't used for this
translation method. Use the equivalent properties instead, such as Caption and Tooltip . Then, make sure the
manifest is set up to generate the /Translations folder and use the generated .xliff files for translations of the
extension. For more information, see Working with Translation Files.

Pages
The ActionContainer elements in AL have been renamed; the following table lists the renamed elements:

C / SIDE A L L A N GUA GE DEVELO P M EN T EN VIRO N M EN T

ActionItems Processing

ActivityButtons Sections

HomeItems Embedding

NewDocumentItems Creation

RelatedInformation Navigation

Reports Reporting

For instance, area(Sections) can be defined inside the actions section of the page.
Likewise, Container and ContainerTypeelements in C/SIDE are renamed to
area(Content|FactBoxes|RoleCenter) and can be defined inside the layout section of the page.

NOTE
For backward compatibility, we continue to support adding non-part pages as parts. It's a good idea to redesign your
page to only use Card part or List part, as we may remove support in a future update.

For syntax examples, see Page Object and Page Extension Object.
Naming
Controls, actions, and methods names must be unique on pages. In C/SIDE, you could create a Part control with
the same name as a method, which would give you an error at runtime. It's now prevented by disallowing
duplicates. Similarly, trigger and trigger event names are disallowed on matching application object
types. Likewise, actions and fields could have same names before, but that would have prevented page
testability access, and will now throw a compilation error.

NOTE
Name on Controls and Actions on Pages is mandatory now.

Property dependencies
For some properties to work, they require you to set another property. An example is PromotedCategory , which
requires that you've enabled the property Promoted . The following table lists some of the properties that have
this dependency.

P RO P ERT Y DEP EN DS O N T H E P RO P ERT Y. . .

PromotedCategory Promoted

PromotedIsBig Promoted

ValidateTableRelation TableRelation

SourceTableTemporary SourceTable

RunPageMode RunObject

Limited functionality
The InitValue property of type Duration isn't allowed in the AL Language development environment. The
InitValue of type DateTime is only allowed for the value 0DT .

See Also
Developing Extensions
Get Started with AL
AL Development Environment
Adding Help Links from Pages, Reports, and
XMLports
2/6/2023 • 2 minutes to read • Edit Online

When creating new pages, you can specify which Help file to open if the user selects the Learn more links in the
UI of Business Central.
The context-sensitive Help link is generated based on a configuration setting in the app.json file and the name
of the relevant Help file that you specify as part of the metadata for the page object. For more information, see
Configure Context-Sensitive Help.

Examples
The following examples show how you can specify the ContextSensitiveHelpPage property from new pages,
reports, and XMLports:

page 50100 MyPageWithHelp


{
ContextSensitiveHelpPage = 'sales-rewards';
}

report 50100 MyReportWithHelp


{
requestpage
{
ContextSensitiveHelpPage = 'sales-rewards';
}
}

xmlport 50100 XmlPortWithHelp


{
requestpage
{
ContextSensitiveHelpPage = 'sales-rewards';
}
}

In all three examples, the ContextSensitiveHelpPage property is set to point at the same Help file. This is because
all three example objects support the same feature that is explained in the sales-rewards Help article. In your
app, you can choose to structure the Help differently.

See Also
Configure Context-Sensitive Help
Translating Base App Help
JSON Files
Page Object
Report Object
XMLport Object
Table Object
ContextSensitiveHelpPage Property
Working with Translation Files
2/6/2023 • 5 minutes to read • Edit Online

Dynamics 365 Business Central is multi-language enabled, which means that you can display the user interface
(UI) in different languages. In Dynamics 365 Business Central, this is done using XLIFF files, which is a
standardized format used for computer-based translations.

TIP
Optionally, use the Dynamics 365 Translation Service to get translations for your target languages. For more information,
see Translate user interface files.

For an overview of how translations are applied, see Translations Overview.

Generating the XLIFF file


To add a new language to the extension that you've built, first, you must enable the generation of XLIFF files. The
XLIFF file extension is .xlf. The generated XLIFF file contains the strings that are specified in properties such as
Caption , CaptionML , and Tooltip .

NOTE
To submit an app to AppSource, you must use XLIFF translation files.

In the app.json file of your extension, add the following line:

"features": [ "TranslationFile" ]

NOTE
If the Incremental Build setting is enabled in the AL Language extension configuration then all translations will be
ignored, even though the "features": [ "TranslationFile" ] setting is specified in the app.json file. For more
information, see AL Language Extension Configuration. The same is true when using RAD publishing, all translations will
also be ignored. For more information, see Work with Rapid Application Development.

Now, when you run the build command (Ctrl+Shift+B ) in Visual Studio Code, a \Translations folder will be
generated and populated with the .xlf file that contains all the labels, label properties, and report labels that
you're using in the extension. The generated .xlf file can now be translated.
IMPORTANT
The ML versions of properties are not included in the .xlf file:
CaptionML
ConstValueML
InstructionalTextML
OptionCaptionML
PromotedActionCategoriesML
RequestFilterHeadingML
ToolTipML
The TextConst Data Type is not included in the .xlf file either.

IMPORTANT
Make sure to rename the translation file before building the extension next time, as it'll be overwritten.

By setting the GenerateCaptions flag in the app.json file, you specify that you want to generate captions based
on the object name for pages, tables, reports, XMLports, request pages, and table fields. If the object already has
a Caption property set, that value will be used. For the table fields, the OptionCaption is used. The syntax is as
follows:

"features": [ "TranslationFile", "GenerateCaptions" ]

GenerateLockedTranslations
APPLIES TO: Business Central 2020 release wave 2 and later

By setting the GenerateLockedTranslationsflag in the app.json file, you specify that you want to generate
<trans-unit> elements for locked labels in the XLIFF file. The default behavior is that these elements aren't
generated. For more information, see JSON Files.

"features": [ "GenerateLockedTranslations" ]

Label syntax
The label syntax is shown in the example below for the Caption property:

Caption = 'Developer translation for %1', Comment = '%1 is extension name', locked = false, MaxLength=999;

NOTE
The comment , locked , and maxLength attributes are optional and the order is not enforced. For more information, see
Label Data Type.

Use the same syntax for report labels:


labels
{
LabelName='LabelText',Comment='Foo',MaxLength=999,Locked=true;
}

And the following is the syntax for Label data types:

var
a:Label'LabelText',Comment='Foo',MaxLength=999,Locked=true;

The XLIFF file


In the generated .xlf file, you can see a <source> element for each label. For the translation, you'll now have to
add the target-language and a <target> element per label. The target-language must be specified in the
format "<language code>-<country code>" , for example "da-DK" , "es-ES" , or "de-DE" . The <trans-unit id>
attribute corresponds to the object ID in the extension. This is illustrated in the example below.

<?xml version="1.0" encoding="utf-8"?>


<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en-US" target-language="da-DK" original="ALProject16">
<body>
<group id="body">
<trans-unit id="PageExtension 50110" maxWidth="999" size-unit="char" translate="yes"
xml:space="preserve">
<source>Developer translation for %1</source>
<target>Udvikleroversættelse for %1</target>
<note from="Developer" annotates="general" priority="2">%1 is extension name</note>
<note from="Xliff Generator" annotates="general" priority="3">PageExtension - PageExtension</note>
</trans-unit>
</group>
</body>
</file>
</xliff>

NOTE
You can have only one .xlf file per language. If you translate your extension to multiple languages, you must have a
translation file per language. There is no enforced naming on the file, but it's a good practice to name it
<extensionname>.<language>.xlf .

When the extension is built and published, you can change the language of Dynamics 365 Business Central to
view the UI in the translated language.

Translating other extensions


To translate other extensions, for example, when adding translations to the Base Application, you must reference
the project to be translated using the dependencies section in the app.json file. For more information, see
JSON Files. When the dependencies are set, you can add xliff files in your current project that translates the
object captions of the referenced extension. Create a directory named Translations , in the root of the extension,
and place the translated xliff file there. When your extension is then built and published, change the language of
Dynamics 365 Business Central to view the UI in the translated language.
NOTE
When translating other extensions, make sure that the attribute original in the <file> element in the xliff file is not
set to the name of the current app. Otherwise, translations are only used to translate labels in the same app.
For apps where translations are meant to translate the current app, the generated xliff file will have the correct value of
the app name.

Use the <trans-unit id> of the label where it was defined


In order to translate other apps, you must use the <trans-unit id> of the original property, not the one of an
extension object as that might have been modified.
If MyPage is defined as:

page 50000 MyPage {


Caption = 'Base Page'
}

and it has <trans-unit id> for the page corresponding to Page 2931038265 - Property 2879900210 .
And if the following page extension of MyPage called MyPageExtension :

pageextension 50000 MyPageExtension extends MyPage


{
Caption = 'Extension Page';
}

has <trans-unit id> for the page extension corresponding to PageExtension 1716690578 - Property 2879900210 ,
then if you want to change the caption on the page, you must use the ID Page 2931038265 - Property 2879900210 ,
which is the <trans-unit id> of the original property.

See Also
Working with labels
Working with multiple AL project folders within one workspace
JSON Files
Translate user interface files using the Dynamics 365 Translation Service
Instrumenting an Application for Telemetry
2/6/2023 • 2 minutes to read • Edit Online

This article describes how you can implement custom telemetry signals in your application for emitting
telemetry data. This data can then be collected and visualized for analyzing the application against the desired
business goals, troubleshooting, and more.

Telemetry overview
One aspect of event logging is the data collection about the working and deployment infrastructure of an
application to diagnose conditions and troubleshoot problems that affect its operation and performance. For
example, this type of event logging includes Business Central Server events and trace events like SQL and AL
method (function) traces.
Another aspect of logging is telemetry, which is the collection of data about how your application works in
production. Telemetry can tell you about specific activities that users perform within the application in the
production environment. Telemetry also helps troubleshooting in those instances where you aren't able to
reproduce the conditions experienced by the user or have no access to the user's environment. Telemetry can be
divided into different categories, like: telemetry for engineering, telemetry about the business, telemetry for
customers.

Creating custom telemetry signal


There are two different resources where telemetry trace signals can be sent for monitoring and analyzing: Event
Log and Microsoft Azure Application Insights. By default, the Business Central application is instrumented to
emit several system telemetry trace signals to these destinations. Custom telemetry trace signals enable you to
send telemetry data from anywhere in the application code to either of these destinations.
The procedure for creating custom telemetry signals is different for each resource. Your choice might also
depend on whether you're developing for Business Central online or on-premises.

RESO URC E DESC RIP T IO N O N L IN E O N - P REM ISES M O RE IN F O RM AT IO N


RESO URC E DESC RIP T IO N O N L IN E O N - P REM ISES M O RE IN F O RM AT IO N

Application Insights Create custom See...


telemetry signals
that are sent to an
Application Insights
resource in Azure.
Application Insights
is a service hosted
within Azure that
gathers telemetry
data for analysis and
presentation.

Extension developers
can specify whether
the signal is only sent
to the extension
publisher or also to
the VAR partner
telemetry resource.

You create these


custom trace signals
by using the
LOGMESSAGE
method in the code.

Event Log Create custom See...


telemetry trace
signals that are sent
to the Event Log of
the Business Central
Server machine. You
create these custom
trace signals by using
the SENDTRACETAG
method in the code.

NOTE
Using Application Insights is recommended.

See Also
Monitoring and Analyzing Telemetry
Monitoring Business Central Server Events
The SMB Opportunity for App Publishers
2/6/2023 • 3 minutes to read • Edit Online

Our mission is to empower every individual and every organization on the planet to achieve more. Particularly,
focusing on those 78 million small and mid-sized businesses (SMB) worldwide that passionately want more
resiliency in their tech intensity and their capability of transforming products and services to face the challenges
in the marketplace. To embrace the constant change and grow, every organization must have a business
application that breaks down the silos of data, processes, and workflow in their operations. This insight enables
employees to respond to daily challenges and opportunities with agility. Market research shows that the
business applications opportunity for software companies in the SMB space is predicted to be 51 billion dollars
by 2025. As a developer, you want to make sure you bet on the winning platform. The BizApps market growth in
this area is 17%; however Dynamics 365 platform growth is increasing at 47%!

Dynamics 365 Business Central


Dynamics 365 Business Central is an all-in-one business management solution that connects operations for
SMBs. It ensures business continuity with a cloud solution that connects sales, service, finance, and operations to
help teams adapt faster and deliver result. Business Central provides app publishers with a modern business
platform that can easily connect to, extend and build on—with little to no code required.

The Microsoft commercial marketplace


Microsoft AppSource is part of Microsoft's commercial marketplace where customers can find, try to get
business solutions apps. It's the launch pad for your joint go-to-market activities with Microsoft and a medium
for business growth. By using launch promotion, demand generation, and joint sales and marketing, your offer
portfolio on AppSource can be the centerpiece of your cloud business engine.
In November 2020, Microsoft AppSource had more than 3 million monthly active users and +20,000 apps.
Specifically, for Business Central, there are more than 1500 apps available and the number is growing fast.

Go-to Market scenarios


As an AppSource publisher, you can focus on the following two scenarios with Business Central and Microsoft
AppSource:
Connect
Add-on
Connect
Connect your existing online service with the Business Central through a powerful API. Following are some
examples of existing connect apps that you can find on AppSource:
Square payments, which allows you take payments with a Square terminal.
Certify which allows users to post expense reports using Certify.com
Scaptify, which connects your Shopify store with Business Central
Learn more about the API to build connect apps: Getting Started Developing Connect Apps
Add-on
You can extend the default capabilities in Business Central to add extra productivity features or industry
functionality to fit the needs of your customer base. The possibilities are plentiful.
In countries, where Business Central isn't localized by Microsoft, you can extend Business Central based on local
requirements to respond to the regulatory or competitive needs of that market.
Here are a few examples of some apps that extend Business Central:
E-Ship and E-Receive from Lanham Associates, which extends warehouse management with barcoding
and labeling, scanning functionality, and interfaces with carriers and weigh scales.
Continia Document Capture, which is an end-to-end solution for document recognition, invoice approval
and digital archiving.
Philippines localization from Pasi, which computes the withholding tax as mandated by the Philippine
government for both customers and vendors.
SwissSalary 365, which is a certified and flexible payroll app that's intuitive and easy to use for the Swiss
market.
Learn more on how to build your app: Get Started with AL

Consultancy services
A large number of business users find it easy to buy consultancy services to research, deploy and manage apps.
Therefore, next to providing Apps, a publisher can also market consultancy services on Microsoft AppSource to
connect with buyers. The offered services could be assessments, briefings, workshops, proof of concepts, and
implementations. In general, the services are typically fixed in scope and duration. They're offered at a fixed price
or free, and have a defined outcome.
Here are a few examples of consultancy services provided by publishers:
Unified Commerce Readiness Intro: 1-Hr Assessment In this 1 hour assessment, LS Retail assesses how a
4-day engagement helps them with implementing their Unified Commerce Cloud solution based on
Microsoft Dynamics 365.
NAV-X Commission Mgt Gold 4-Hr Implementation In this 4 hour implementation workshop, NAV-X
supports the customers in implementing their commission management app.
Learn more about Consultancy Services.

See also
Get Started with Building Apps
Get Started with Building Apps
2/6/2023 • 8 minutes to read • Edit Online

Dynamics 365 Business Central is a business management solution that helps companies connect their services
and operations to streamline business processes, improve customer interactions and make better decisions.
With this modern business platform, you have the convenience to quickly tailor, extend, and build applications
so that they fit your specific needs with little to no code development.
Build a business app for a specific industry, process, or department such as HR, finance, marketing or
operations. Then, publish your app to the Microsoft commercial marketplace, where customers can find your
app, try it and get in touch with you. For more information, see What is the Microsoft commercial marketplace?.
Learn how you can become a Business Central app publisher in six steps in this article.

Step 1: Become a partner


When you become a Microsoft partner, you get access to the Microsoft resources needed to build, market, and
sell your apps. You don't have to be a Microsoft partner to begin developing your apps. But, all of the steps
below are required to gain access to the programs that enable you to publish, market, and sell your apps for
Business Central.
Obtain your work account
Your work account is the email address provided to you by your company. This email is usually in the format
you@yourcompany.com . For more information on work accounts, see Link your work Account.

Join the Microsoft Partner Network


Microsoft Partner Network (MPN) membership unlocks our best resources to differentiate your business, take
your product to market, and sell your solutions. To become a partner, you must join the Microsoft Partner
Network (MPN), at which time you will be assigned an MPN ID. MPN membership is free to all partners; you can
enroll in the MPN here.
Once signed up, you will get an MPN ID – your gateway to access all the membership resources and benefits for
your partnership with Microsoft. There is no cost to obtain a MPN ID as a Network member, and with options to
upgrade to an Action Pack subscription or work toward a competency, you can access even more benefits.
Set up your Partner Center account
Once you have joined the Microsoft Partner Network (MPN), you can set up your Partner Center (PC) account.
The Microsoft Partner Center is a generic portal where partners can sell and manage customer subscriptions for
Microsoft services, such as Microsoft 365, Azure, Dynamics 365, and others, as well as for some third-party
products. For more information, see the Partner Center documentation.
Your Partner Center account provides you with access to pricing information, tools and services, and enables
you to manage admin credentials for your company's work account. Partner Center is also where you can
purchase or renew subscriptions to Microsoft Action Packs, create a business profile to receive and manage
sales leads from Microsoft, and see if you qualify for co-selling opportunities.

Step 2: Register as a publisher


The first step to becoming a publisher is to register in Partner Center (PC). PC is where you submit your apps for
publication, promote them, and manage your offers. To begin the registration process, you must complete these
steps. One of our team members will follow up to help you complete your registration. Once registered, you can
access PC.
For more information, see Partner Center Account.
PartnerSource Business Center (PSBC ) account
To develop apps for Business Central, you're required to be known as a Business Central developer. You must
also have a unique development license file with a specific object range.
To obtain an object range for developing a Business Central app, you must have access to PartnerSource
Business Center (PSBC). Either of the following agreements gives you access to PSBC, which is a first step
towards getting a development license:
An active Partner Registration Agreement (PRA)
A Registered Solution Program Addendum (RSPA)
The relevant contract can be requested through your local Regional Operations Center (ROC) Contracts and
Agreements Team below:
mbscon@microsoft.com if you're based in Europe, the Middle East, or Africa
mbsagree@microsoft.com if you're based in the Americas
mbslques@microsoft.com if you're based in the Asia Pacific region.

Step 3: Your unique app specifications


Requesting an object range
When you develop an app for Business Central, you must request access to an object range that holds some
objects for your solution. To avoid overlap between objects used in different solutions, each partner is assigned
many objects in a unique object range. For example, a partner is assigned the object range 70,001,000 –
70,001,999. The object range gives them 1000 numbered objects that they can use to develop Business Central
solutions.
Depending on where you'll deploy your Business Central solution, online or on-premises, you can use different
licensing methods and object ranges.
There are currently two available ranges that you can request. Both have some characteristics to keep in mind:
RSP Object Range (ID range 1,000,000-69,999,999)
This object range is tied to the RSP Program details.

IMPORTANT
We currently advise new publishers to not request an RSP object range

App Object Range (ID range 70,000,000-74,999,999)


This object range was originally designed just for apps in the Microsoft commercial marketplace to be
used in Business Central online.

IMPORTANT
We currently advise new publishers to request an app object range.

Currently, you can implement apps developed in both the RSP range and the app object range in Business
Central online and on-premises, as well as partner-hosted.
You can request an object range by downloading the object range request form here. After completion, send
them to your Regional Operational Center (ROC) for processing:
mbscon@microsoft.com if you're based in Europe, the Middle East, or Africa
mbsagree@microsoft.com if you're based in the Americas
mbslques@microsoft.com if you're based in the Asia Pacific region.
Downloading your development license file
After your Regional Operational Center has processed your Agreements and Object Range Request forms,
download your company's unique developer license from PartnerSource Business Center. Find it in the license
key configuration section under the developer tools section.
Register your unique prefix or suffix
In your extension, the name of each object must contain a prefix or suffix that is registered for your publisher
name. For more information about the use of affixes and the registration process, see Benefits and Guidelines
for using a Prefix or Suffix.

Step 4: Getting access to preview bits


Get access to preview builds by joining Microsoft Collaborate.
In Microsoft Collaborate, you get access to a set of Business Central builds:
The current major version
An upcoming major version
Daily builds
You must have the following prerequisites to register on Microsoft Collaborate:
Azure Active Directory (Azure AD).

NOTE
If you have Microsoft 365, then your company most likely has Azure AD.

Azure AD Global Administrator permission

NOTE
To find out if your company has an Azure AD account, check with your system administrator.

Step 4 A: How your Global Administrator must register for Collaborate


Only your company's Global Administrator can start the onboarding to Collaborate. They must register
at https://aka.ms/Collaborate, choose the Get Star ted action, and then complete the registration form.
The administrator can then add the relevant colleagues.
Optional Step: Add your coworkers to Microsoft Collaborate
To add coworkers:
1. Sign in to Microsoft Collaborate with your Global Administrator account at aka.ms/Collaborate.

2. Choose the settings icon in the top-right corner of the page, got to on account settings, and choose
user management .
3. Choose the grey ADD USERS button, and leave the default choice to Add existing users as-is. Now,
you can search for the user(s) that you want to add to Collaborate. To add them, you need to choose them
from the menu, and then choose the grey ADD SELECTED button.
4. You've successfully added your coworkers to Collaborate. Users can now sign in to Microsoft Collaborate
using the following link: aka.ms/Collaborate
Step 4 B: Getting access to the available builds and engagements
Once you've successfully registered on Microsoft Collaborate, Microsoft must assign you to the right programs,
and engagements before you can see the preview bits. Contact Dyn365BEP@microsoft.com and provide them
with information about the relevant users. the following table illustrates the type of information that you must
submit:

P UB L ISH ER DISP L AY W O RK A C C O UN T
NAME M P N ID F IRST N A M E L A ST N A M E EM A IL

Contoso 12345 Eugenia Lopez Eugenia.Lopez@Cont


oso.com

Contoso 12345 Quincy Watson Quincy.Watson@Con


toso.com

After sending the email, expect a response from Microsoft within 1-2 business days.

Step 5: Resources while you develop your solution


Find below some guiding resources on how to develop your apps for Business Central.
Microsoft Learn
Learn new skills and discover the power of Microsoft products with step-by-step guidance. Start your
journey today by exploring our learning paths and modules.
Microsoft Docs
Find The developer and administration content on Microsoft Docs
Join the conversation
In the dedicated Yammer network, join the conversation on developing apps
Join the monthly Office hour calls
Join the monthly Office hour calls to learn more about a hot topic.
Get coaching from experts
Need help with developing your apps? There's a community of ISV Development Centers specialized in
Business Central ready to engage with you.
Set up DevOps processes for your project
It's recommended that all partners set up DevOps processes to ensure that this validation process happens
automatically and regularly.
You can find resources for how to set up full plug-and-play DevOps processes using AL-Go for GitHub:
https://aka.ms/AL-Go.
Step 6: Publish your app in the Microsoft commercial marketplace
Once your app is ready for submission, you can list your app in the Microsoft commercial marketplace by
submitting it in Partner Center. For more information, see Create a Dynamics 365 Business Central offer.
Before you submit, we recommend that you review the technical validation checklist and marketing validation
checklist. The two articles list all requirements that you must meet before you submit an app for validation.
If you don't meet these mandatory requirements, your extension will fail validation

See also
The SMB Opportunity for App Publishers
The Lifecycle of Apps and Extensions for Business Central
Update Lifecycle for AppSource Apps FAQ
Maintain AppSource Apps and Per-Tenant Extensions in Business Central Online
Microsoft Responsibilities for Apps on Business Central online
Marketing Validation Checklist
2/6/2023 • 3 minutes to read • Edit Online

The storefront details on AppSource are the first impression that prospects get regarding your offer. First
impressions last, so make sure to invest some time in developing the content on the storefront, so it gives a
good impression from the beginning. Failing to do so will jeopardize the hard work you put in, when developing
your offer, likely leaving the prospect confused or looking elsewhere. Accordingly, we recommend you put in the
time, effort and due diligence when developing this content.
You use Partner Center to submit your offer to AppSource. In the following, you can find information on all the
marketing-related items that you need to fill out in Partner Center prior to submitting your app to AppSource.
Follow this marketing validation checklist and get your app passed on the first submission.

What do I need to know before I begin?


You need to have the following three items in mind, when you're creating your storefront and marketing
material.

IT EM REQ UIREM EN T DETA IL S

Branding Make sure to read the branding Read more


guidelines carefully before you start
referencing the product name.

Language Discover what to consider for each Read more


storefront detail when it comes to
language.

Microsoft images Make sure not to use any Microsoft Read more
images (for example, the Business
Central icon or Dynamics 365 logo).

How do I fill out the marketing section in Partner Center?


The following section walks you through the marketing-related components, that is, offer setup, properties, offer
listing, and availability, which you need to fill out in Partner Center prior to submitting your app to AppSource.
Offer Setup
IT EM REQ UIREM EN T DETA IL S

App type Read more about the types of apps Read more
you can submit to AppSource.

Listing type How do you want potential customers Read more


to interact with your offer?

Customer leads Provide connection details to the CRM Read more


system where you would like to send
customer leads.

Properties
IT EM REQ UIREM EN T DETA IL S

Categories Choose a primary, a secondary, and up Read more


to four subcategories.

Industries Choose up to two industries for your Read more


offer.

App version Specify the version number of your Read more


offer.

Terms and conditions Outline the terms and conditions that Read more
the customer must accept before they
can use your offer.

Offer listing
IT EM REQ UIREM EN T DETA IL S

Offer name Enter a descriptive name for the offer. Read more

Offer summary A single sentence summarizing the Read more


purpose or function of the offer.

Description text Make an elaborate and compelling Read more


description that outlines the benefits
and usage scenarios of your offer
(include supported editions, countries,
and languages).

Search keywords Add search keywords to help users Read more


find your offer when they search in the
marketplace.

Products your app work with Add specific products that your app Read more
works with.

Help link The link to your offer’s learning Read more


resources.

Privacy policy link The link to your offer’s privacy policy. Read more

Support link The link to your offer’s support page. Read more

Supporting documents Add supporting sales and marketing Read more


assets such as white papers, brochures,
checklists, or PowerPoint presentations.

Logos Upload a large size logo file with Read more


dimensions between 216 pixels x 216
pixels and 350 pixels x 350 pixels.

Screenshots Provide a minimum of three Read more


screenshots that showcase your offer.
IT EM REQ UIREM EN T DETA IL S

Videos (optional) Add up to four videos that Read more


demonstrate your offer. These should
be hosted on an external video service.

Availability
IT EM REQ UIREM EN T DETA IL S

Markets (countries) Choose the markets that your app is Read more
available in (make sure that it
resembles the supported countries
paragraph in the description text).

Hide key The hide key is a token that is used to Read more
view the preview of your offer in
AppSource before going live.

How does my offer look when it's live on AppSource?


Technical Validation
2/6/2023 • 8 minutes to read • Edit Online

Below you'll find a checklist of all requirements that you must meet before submitting an extension for
validation. You'll also find a description of how the Business Central Validation team is performing technical and
manual validation and how you can implement a validation pipeline to perform the same technical validation
yourself.

TIP
If you have questions around validation for your app, see Technical Validation FAQ for more information about who to
contact.

Technical Validation Checklist


If you don't meet these mandatory requirements, your extension will fail validation. To get code validation
helping you bring your extension package to AppSource, you can enable the AppSourceCop code analyzer. For
more information, see Using the Code Analysis Tool.

REQ UIREM EN T EXA M P L E/ GUIDA N C E

Develop your extension in Visual Studio Code. Developing AL Language extensions

The app.json file has mandatory properties that you must Mandatory app.json properties
include. The 'name', 'publisher', and 'version' properties must
match the values set in your offer description. Here you can
also read more about dependency syntax and multiple
countries per a single app syntax.

Coding of Date must follow a specific format (no longer Use the format yyyymmddD . For example, 20170825D .
region-specific)

Remote services (including all Web services calls) can use Guidance on HTTP use
either HTTP or HTTPS. However, HTTP calls are only possible
by using the HttpRequest AL type.

Only JavaScript based Web client add-ins are supported. The Control Add-Ins
zipping process is handled automatically by the compiler.
Include the new AL controladdin type, JavaScript sources,
and build the app.

The .app file must be digitally signed. Sign an APP Package File

Set the application areas that apply to your controls. Failure Application Area guidance
to do so will result in the control not appearing in Dynamics
365 Business Central.

Permission set(s) must be created by your extension and Exporting Permission Sets
when marked, should give the user all setup and usage Managing Users and Permissions
abilities. A user must not be required to have SUPER
permissions for setup and usage of your extension.
REQ UIREM EN T EXA M P L E/ GUIDA N C E

Before submitting for validation, ensure that you can How to publish your app
publish/sync/install/uninstall/reinstall your extension. This
must be done in a Dynamics 365 Business Central
environment .

Thoroughly test your extension in a Dynamics 365 Business Testing Your Extension
Central environment.

Don't use OnBeforeCompanyOpen or OnAfterCompanyOpen Replacement Options

Include the proper upgrade code allowing your app to Upgrading Extensions
successfully upgrade from version to version.

Pages and code units that are designed to be exposed as Web Services Usage
Web services must not generate any UI that would cause an
exception in the calling code.

You're required to register affixes for your publisher name Prefix/Suffix Guidelines
and to use them in your extension.

You're required to register an ID range for your publisher Object Ranges


name and to use it in your extension.

We strongly recommend you're using automated testing, Testing the Advanced Sample Extension
using the AL Test Toolkit. You aren't required to include the
test package with your extension.

DataClassification is required for fields of all tables/table Classifying Data


extensions. Property must be set to other than
ToBeClassified .

You must use the Profile object to add profiles instead of Profile Object
inserting them into the Profiles table.

Use addfirst and addlast for placing your actions on Placing Actions and Controls
Business Central pages. This eliminates breaking your app
due to Business Central core changes.

The extension submitted must not be a runtime package. Creating Runtime Packages

The extension submitted must use translation files. Working with Translation Files

The extension submitted must specify the Application The Application manifest property is required in order to
manifest property. compute the minimum release of Business Central targeted
by your submission. For more information, see Computation
of Releases for Validation

Technical validation performed by the Business Central validation


team
The primary responsibility of the technical validation is to ensure that the Business Central online service is
stable and that the apps can be installed and run without destabilizing the service.
The technical validation is fully automated and validates the requirements defined in the technical validation
checklist above.

IMPORTANT
It is recommended that all partners run the self-validation documented below before submitting apps for validation to
maximize chances of validation success.

1. The manifest of all extensions in the submission is validated. If any mandator y proper ties or required
proper ty values are missing, the submission is rejected..
2. The registration of affixes for the publisher name of all the extensions in the submission is validated. If the
publisher name does not have any registered affixes, the submission is rejected.
3. The signature of all extensions in the submission are validated. If any extension is not signed or its
signature is not valid, the submission is rejected.
4. The consistency of the main extension information (name, publisher, version) is validated against the offer
description. If any differences are noticed, the submission is rejected.
5. The extensions in the submission are validated. If any runtime packages are present, the submission is
rejected.
Once the extension has passed these first validation steps, the minimum release for your submission is
computed as described in Computation of Releases for Validation.
For each countr y and each release targeted by your submission, the following steps are run for each
extension in the submission:
1. If the extension with the same version has already been validated for the country, further validation for this
extension is skipped.
2. The set of dependencies for your extension is resolved. Any unresolved dependencies will cause the
submission to be rejected. If you include extensions created by Microsoft in your submission, it
will also be rejected.

NOTE
You are required to include the dependencies for your extension as part of your submission only if you are submitting a
newer version for them. If you do not include them in your submission, they will be downloaded automatically if they are
available in Business Central for the targeted countries/regions. If you are making your libraries available in new countries,
you should increase the version number.

3. The set of baselines for your extension is resolved by using the App Management API.
4. The extension is compiled against the set of dependencies resolved. If the compilation fails, the
submission is rejected.
5. The extension is tested against the resolved baselines using the AppSourceCop analyzer. If any violations or
breaking changes are identified, the submission is rejected.
6. If the runtime version of the extension is not suppor ted by the release targeted, the submission
is rejected.
If all extensions in the submission succeed the validation for each country and release without errors, the
submission is accepted..

Running technical validation yourself


With the latest version of BcContainerHelper, you can run a single command, which should perform the same
validation steps and give you a good indication of whether your apps will pass validation or not:
$validationResults = Run-AlValidation `
-validateCurrent `
-installApps @( "path/url to your foreign dependencies, apps which will not be part of the validation
(or blank if this is the first)" ) `
-previousApps @( "path/url to your previous version of the .app files (or blank if this is the first)" )
`
-apps @( "path/url to the new version of the .app files" ) `
-countries @( "countries you want to validate against (f.ex. us,ca)" ) `
-affixes @( "affixes you own (f.ex. fab,con)" ) `
-supportedCountries @( "supported countries (f.eks. us,ca)" )
$validationResults | Write-Host -ForegroundColor Red

All array parameters can also be specified as a comma-separated string. For more information, you can also
check this blog post Run-AlValidation and Run-AlCops.
Please include app and all library apps in both previousApps and apps and please include all countries on which
you want to validate.

NOTE
The Run-AlValidation cannot see whether the affixes to specify have been correctly registered with Microsoft using your
MPN ID and app publisher name, please make sure registration is in place.

IMPORTANT
The computer on which you run this command must have Docker and the latest BcContainerHelper PowerShell module
installed and be able to run Business Central on Docker.
If you are having issues with Business Central on Docker, you might be able to find help here:
https://freddysblog.com/2020/10/12/troubleshooting-business-central-on-docker.
You can use https://aka.ms/getbc?artifacturl=bcartifacts%2fsandbox%2f%2fus%2flatest to create an Azure VM, which has
all prerequisites installed to run Business Central on Docker.

NOTE
It is recommended that all partners set up DevOps processes to ensure that this validation process happens automatically
and regularly.
You can find resources for how to set up full plug-and-play DevOps processes using AL-Go for Github: https://aka.ms/AL-
Go.

How to get more information on the technical validation failures?


Detailed validation results are automatically logged to the ApplicationInsights storage account specified by
instrumentation key in the manifest of the main extension in your submission.
In order to enable partner telemetry in your extension, you must specify the
applicationInsightsConnectionString property in the manifest (app.json) of your extension. For more
information about this property, see JSON files.
In order to get started on analyzing your validation results, you can use this troubleshooting guide Dynamics
365 Business Central Troubleshooting Guide (TSG) - AppSource Submission Results (SaaS).
For more information about the signals sent during the technical validation, see Analyzing AppSource
Submission Validation Trace Telemetry.
Against which releases of Business Central is your submission
validated?
Extensions submitted to the AppSource marketplace are validated for all countries specified in the submission
against all the release targeted by the submission. As part of the validation, the minimum release for your
submission is computed. The extensions are then validated for all releases from this minimum release to the
current release in production. For example, if the minimum release for your submission is 18.0 and the latest
minor release in production is 18.3, your submission will be validated against 18.0, 18.1, 18.2, and 18.3.
The minimum release for your submission is computed based on the application property specified in the
app.json of your extension.

NOTE
If multiple extensions are contained in your submission, the minimum release for the submission is the highest minimal
release computed for each of the extensions in the submission.

IMPORTANT
The minimum release computed for your submission also defines the availability in Business Central of all the extensions
in your submission.
For example, if the minimum release computed is 18.1, your extensions will be available starting from release 18.1.

Example
If your extension's manifest is defined as follows, the minimum release where your extension can be installed is
18.0 because the manifest requires the Application extension to be available with a version higher or equal to
18.0.0.0.

{
"application": "18.0.0.0",
}

The minimum release of the extension is then 18.0.


For AppSource extensions, it's now required to use the application property instead of explicit dependencies
on the Base Application and System Application . For more information, see The Microsoft_Application.app File
and AS0085.

See Also
Developing AL Language extensions
How to Make Compelling Videos
2/6/2023 • 9 minutes to read • Edit Online

Why use video? It's worth investing time and resources to create marketing videos for your app, it's taken
seriously in a business environment.

Reasons why video is a superior medium


Videos offer a rich, stimulating communication medium that engages multiple senses.
Video engages the mind and triggers emotions, which makes it more compelling than text-based content.
Our brains have an easier time processing visual stories than bullet points or straight facts.
A recent Demand Gen survey indicated that 58% of B2B buyers consume video content, while Hyperfine media
states that 59% of executives would rather watch video than read text. Also, 50% of executives look for more
information after seeing a product/service in a video.

Speak to Specific Personas in your videos


You should create a video for each of the three core personas in the company:
WHY persona: Owner/executive/leadership
HOW: Business line manager
WHAT: IT buyer, User
A horizontal generic message that attempts to speak to everyone will likely not reach anyone in an emotionally
engaging way. Wasting a prospect’s time by requiring the prospect to listen to irrelevant data or information will
only create frustration and lead the prospect to form a negative bias towards your company.

Choose the video format that is relevant for the audience that you
want to target
Video type 1: “Why” video
How to set up “Why” videos
Recommended length: 60-90 seconds
Purpose:
Your video should clearly communicate WHY prospects need to buy your solution now.
Focus:
Make sure the prospect is the hero of the story, not you or your company. Prospects aren't interested
in hearing about your company at this stage. They're simply trying to determine if what you offer is of
value to THEM.
Your video should speak to the principal challenges and goals of your core decision-maker persona.
Describe the desired end state they'll achieve by using your app.
A client/customer speaking about the benefits they received from your app is far more credible and
compelling than anyone from your organization.
Don’t only rely on “features” to acquire new customers.
How to speak to a WHY persona in a video
Target audience:
Owner/executive/leadership
They have limited time and financial resources as well as many competing priorities and resource
requirements
You need to elevate the discussion to a strategic level, where you highlight market share,
competitiveness, profitability, differentiation, revenue loss, and more.
Message:
The question you must answer beyond a doubt is WHY should they invest the time and money to buy
your app? What will they get out of it?
Why should they spend money on a new system now? Can’t they put it off?
The WHY messaging teaches people something and it's industry specific and results oriented, as well
as being memorable. It engages the emotional/limbic brain and leads to meaningful action.

Video type 2: “How & What” video


How to set up “How and What product videos”
Recommended length: Up to 3 minutes.
Purpose:
This video goes into greater depth communicating the main benefits of your app and HOW you solve
your prospects’ problems. You can include some WHAT content. • Focus:
Demonstrating the proof of your claims is critical during this video.
Show specific dashboards or visually show how you address prospect challenges.
If possible, use contrast to create desire and a sense of urgency. For example, you could show a
complex, ugly data-filled forecast spreadsheet next to a beautiful visual dashboard stating “your sales
forecast before and after.”
How to speak to a HOW persona: (Business line manager)
Target audience: Business Line Manager
HOW focuses on the operational benefits your solution will provide and HOW your organization will
support the implementation.
Speaking to the HOW persona starts to separate you from the pack. • Message: o HOW content is
VISUAL in nature and ACTION oriented. It allows your prospects to identify with you at a
FUNCTIONAL business level and to add on with you. It provides evidence that your organization has
relevant industry experience. Tribal acceptance increases, while risk decreases.
HOW messaging begins to appeal to the limbic brain because it's focused primarily on emotional
business pains and problems.
How to speak to a WHAT persona: (IT buyer, User)
Target audience: IT-buyer, User
WHAT people are often tasked with finding a solution and are important influencers in the decision,
but they aren't the financial decision makers, and their opinions are easily overturned by HOW and
WHY people in the organization.
Therefore, don’t invest all of your marketing time, money, and effort into providing content just for
them.
Message:
You need to survive the WHAT inquisition and provide information about product-related features,
functionality, and data so that prospects clearly understand your solution offering.
However, this will seldom trigger an emotional response and, therefore, it's likely there will be little or
no emotional engagement with your content.
WHAT content is binary. WHAT content is a commodity. WHAT content is boring. Logical WHAT
content is a necessary evil because many prospects initially go looking for it, but stopping here means
remaining relevant only to WHAT personas.

Video type 3: “Getting started” video


How to set up “Getting star ted videos”
Recommended length: 2–3 minutes maximum.
Purpose: This video should prove it's quick and easy to get up and running with your app.
Target: What personas (Users, It buyers)

Video type 4: “Customer testimony” video


How to set up “Customer testimonial videos” - Recommended length: Up to 2 minutes
Purpose:
Social reinforcement: Customer stories are the best proof of gain.
Focus:
A story coming directly from your client in the form of a testimonial is stronger than having your
prospects take your word for it. If prospects see that other similar people or companies have already
purchased your solution, then their natural response will be to more readily accept it as a solution for
themselves.

Video tips
How to structure your video and practical things to keep in mind when producing videos
How to structure the flow in your video?
Gain immediate attention in the first 10 seconds of the video Stimulate curiosity by including a hook
phrase/comment that will elude to solving a pain point. Ask questions about the prospects’ core business
challenges or ask about something they would like to do but can’t accomplish today.
Highlight the prospects’ problems: Use an empathetic approach when describing their current situation and
demonstrate that you understand their current business challenges. They must relate to this if they're to
continue watching.
Give them new learning Teach them something they don’t know. Demonstrate you have expertise and
knowledge about their business or industry that they might not. Show you can offer strategic value to them.
Paint a picture of a desired outcome they would love to have or state they crave to experience. Highlight the
benefits, rewards, and value they'll enjoy after they purchase from you. Include both what it looks like and
how it will feel.
Prove what you’re saying is true Prospects don’t trust us when we say our products are great. Include
objective and credible proof in the form of data, charts, graphs, quotes, statistics, or testimonials as evidence
of your claims.
Ask them to take action. Include a call to action at the end of all videos. When viewers watch your videos,
they should feel inspired to take the next step towards purchasing. Tell them what to do next and include an
interactive link to the next step in the buying cycle. Use scarcity to compel them to action. Provide a time
limited offer or, for example, say it is “only for the first 20 customers”.
Practical things to keep in mind when producing and distributing your video
Does and don’t when producing your video
Don’t make the video too long As our attention span is 8 seconds the ideal length of video is 90 seconds
(minimum 30 seconds/maximum 2 minutes).
Add interactivity where possible Overlay text, charts, animation, questions etc. Visually call out key messages.
Make sure your audio is high quality.
Make your video easily shareable
Enable your video to be shared on multiple media. Track views and attention span. Observe and measure
viewer patterns so that you can learn from prospects’ actual behaviors and then improve future content.
How to make a good narrative that speak to the right persona in the right way?
Your narrative should have a beginning, middle, and end.
Lead with a story, not with your app or the technology.
Don’t turn your videos into a product pitch.
You’ll build more brand affinity and trust by shedding light on a problem your prospects care about
rather than by pitching your solutions to them directly.
The brain is on alert at the beginning of the video and at the end.
Make sure the first and last 10 seconds are compelling, memorable, and interesting.
Speak directly to a particular persona in the second person.
Don't talk about them in the third person, and avoid using terms like “our clients” and “companies”;
instead, use “you” language as often as possible.
Use many industry specific vocabulary, terminology, and visuals. If possible, film onsite at a
customer’s location rather than in your office or in a studio.
Speak to a particular persona:
Don't try to appeal to everyone at once, as you may not fully engage anyone with this approach.
Keep your delivery casual and authentic to instill trust. Speak directly to the prospect as if you were
having a fireside chat
The prospect should be the hero of the story, that is, don't speak about you and your company.
Ask rhetorical questions that stimulate pain and anxiety in your prospects in order to demonstrate that you
understand their business problems.
For example: Are your margins decreasing? Having cash flow problems because you can’t collect
payments sooner than 90 days? Had another large write-off? Lost an important customer recently
due to a late delivery?
Use visual and auditory language to help the prospect imagine a new possible future.
For example: “imagine seeing”, “picture yourself”, or “how would you like to hear your clients say…”
and so on.
Use contrast whenever possible.
Compare prospects’ experience now versus what it could be after the implementation of your
solution.
Call out your competitive differentiators while anchoring your solution in prospects’ minds so that
they can compare all others against the bar you set.
How to make a good narrative that speak to the right persona in the right way?
Where possible, use tangible, concrete language.
Include quantifiable proof in the form of data or visual pictures.
No vague claims like “transform your business with the cloud”. This is an emotionless statement.
Providing customer references and testimonials is much more compelling and effective than selling your
company or product yourself.
Let others speak for you. A customer testimonial video will always be more believable and compelling
than a video of you saying the same thing.
Surprise and delight them.
Use humor to make them smile. We take ourselves and our problems too seriously. Be warm,
memorable, and unique.
Technical Validation FAQ
2/6/2023 • 21 minutes to read • Edit Online

This article addresses some of the most frequently asked questions around validation of apps for AppSource
submission.

Questions about the validation process


In the following, you can read about how submissions are handled and learn how to address the most common
scenarios.
Against which releases are my apps validated?
The extensions in your submission are validated for all the releases targeted by your submission.
Based on the app.json file of your extension, the service automatically computes the minimum release targeted
by your submission and the extensions are then validated for all releases from this minimum release to the
current release in production. For more information, see the example in Technical Validation Checklist. The
'Target Release' (Current, Next Minor, Next Major) available under 'Supplemental Content' in Partner Center is
ignored and will be removed.

IMPORTANT
The minimum release computed for your submission also defines the availability in Business Central of all the extensions
in your submission.
For example, if the minimum release computed is 18.1, your extensions will be available starting from release 18.1.

NOTE
30 days before the release of a new Business Central major version, all submissions are validated against the upcoming
release. The apps in your submission must then be compatible with the upcoming release. The goal is to ensure that your
customers won't be blocked during the upgrade of their environment.

Against which countries/regions are my apps validated?


The extensions in your submission are validated for all the countries/regions targeted by the submission, which
are available in Business Central. You can see which countries/regions you've selected in Partner Center under
Availability > Edit Markets .

When you're adding new localizations in Business Central, these countries/regions can be added to Partner
Center before they're ready in Business Central. If you're targeting a country/region marked as 'Planned' in
Country/regional availability, depending on when your submission is processed, your apps might not be
uploaded to Business Central if the localization isn't yet ready in Business Central. Generally, it's possible to
upload apps for 'Planned' localizations a few weeks before they're officially released. When the localization
becomes available, if you're experiencing issues installing your apps, you should increase the version in the
app.json and submit the packages again in Partner Center. If you're using Azure Application Insights, you can
check whether the country/region was validated using this Troubleshooting Guide (TSG).
Against which baselines are my apps validated?
The service will verify that your extensions don't introduce breaking changes by comparing them to the latest
version available in AppSource for each country validated.
You can know which versions of your extensions were used as baseline during the breaking change validation
by enabling Azure Application Insights in your extension and running this Troubleshooting Guide (TSG).

IMPORTANT
As soon as your app has been uploaded to the AppSource marketplace, it will be used as a baseline during the technical
validation of your next submissions. As a consequence, you won't be allowed to perform breaking changes without
obsoleting the AL objects first and you won't be allowed to perform schema breaking changes; breaking changes on
tables or table extensions. This applies also if your extension isn't used by customers yet. You should then not submit your
app to the AppSource marketplace if you are still developing it and expect to change it in the near future.

Which apps are validated in my submission?


The main app and the libraries required by the main app are validated and uploaded to Business Central. If you
have included libraries, which aren't required by the main app, they'll be ignored during the validation and won't
be uploaded to the service.
For example, let's consider an app A, which has an offer in the AppSource marketplace and A depends on a
library named B, which doesn't have any dependencies. If you create a new submission with A as the main app
and include B, C, and D as libraries, then only A and B will be validated. C and D will be ignored because they
aren't required by the main app A. If B is updated to depend on C and D, then all apps in the submission will now
be validated by the service.

NOTE
If some apps in your submission already have been uploaded to Business Central with the same version for some
countries/regions, then the app will not be validated again for these countries/regions.

IMPORTANT
If one or more libraries in your submission have their own offer, their listing(s) in the AppSource marketplace won't be
updated automatically. In order to keep the listing(s) in sync with the version of the app(s) uploaded to Business Central,
you should submit a submission for their related offer(s).

How long does the 'Automated application validation' take?


During 'Automated application validation', the apps in your submission are validated for each of the
country/regions and each of the releases of Business Central targeted. If you already have a version of these
extensions published to AppSource, then it will also run the breaking change validation using the apps currently
in AppSource as baseline. Depending on the size of your app, the validation time can vary. Submissions are
processed within a few minutes and we expect all submissions to be processed under 3 hours. However, if your
app contains thousands of AL files, this process can take longer. We would then recommend splitting the app in
smaller modules as it would also improve the development experience and the maintainability of your code
base.
How many automated tests do we need to run for validation and how high must the test coverage be?
When setting up your offer in Partner Center, you must still include a test package in 'App Tests Automation', but
it isn't used during the validation of the submission.
Test automation is something we expect you to run, to test your app and to make sure that the quality of your
app is high. We don't run tests of your apps, nor do we have a set value for a required code coverage. Instead,
we rely on you to test your app properly to give your customers a good experience.
When I submit an app to AppSource; do you always make a manual validation based on the provided 'Key
Usage Scenario' document?
When setting up your offer in Partner Center, you must still include a document in 'Key Usage Scenario', but it
isn't used during the validation of the submission.
We don't run a manual validation of the apps anymore. Instead, we rely on you to test that your app provides
your customers with a good experience.
When are my apps ready to be installed in my Business Central environment?
Shortly after the offer publishing process has been completed in Partner Center, your extensions will be
available for installation in Business Central.
Business Central currently doesn't support installing offers at the "Preview creation" step.
When should I include my library apps as part of my submission?
You aren't required to always include the dependencies of your extension as part of your submission.
You're only required to include the dependencies for your extension as part of your submission if you're
submitting a newer version for them. If you don't include them in your submission, they'll be downloaded
automatically if they're available in Business Central for the targeted countries/regions.

NOTE
If you include the dependencies of your extension as part of the submission, these dependency versions will be used
during the validation, even if there are higher versions already available in Business Central.

If you didn't include the dependencies for your app and they aren't available, your submission will fail during the
"Automated Application Validation" stage. Failing to find the dependencies for an extension results in error
messages with the diagnostic codes AVS0005 or AVS0101 .
If you receive an error with the diagnostic code AVS0107 and a message similar to
The extension 'MyApp' by 'MyPublisher' (version '1.2.3.4') has already been uploaded to Business Central for
the country/region 'US'
for one of your library apps, it means that you've already published another .app file for this extension to
Business Central as part of a previous submission. This can happen if you submit a .app file with different
content, or created by a different build (each .app file created has a specific build ID stamped, so building
multiple times the same project results in .app files with different build IDs). If this version of the library is
already available for all countries targeted by your submission, you can just remove the extension from the
submission. If you're making your library available in new countries, you should use the .app file that has
already been uploaded to Business Central or increase the version number in the manifest of the extension (the
app.json file).
My app failed at the "Automated application validation" stage, what do I do next?
At this stage, your extensions are validated to assess whether they meet the requirements specified in the
Technical Validation Checklist.
If this stage failed with an error message similar to
The validation of the submission failed for X out of Y tasks , you must investigate what has caused the error.
If you're using Azure Application Insights, information about the validation results is logged in Azure Application
Insights. You can also use this Troubleshooting Guide (TSG) in order to get started. If you're experiencing issues
with Azure Application Insights, refer to the dedicated section below.
If this stage failed with an error message similar to
The extension 'MyApp' by 'MyPublisher' (version '1.2.3.4') has already been uploaded to Business Central for
the country/region 'US'
, you must update the list of extensions submitted. For more information, see "When should I include my library
apps as part of my submission?".
If this stage failed with an error message similar to
The submission must target at least one existing country/region of Business Central , your submission doesn't
target any countries/regions currently available in Business Central. If your submission targets a country/region
marked as 'Planned' in Country/regional availability, you must wait for the localization to become available in
Business Central and resubmit your offer. Generally, it's possible to upload apps for new localizations, a few
weeks before they're made available to customers.
If this stage failed with an error message similar to
The extension 'MyApp' by 'MyPublisher' (version '1.2.3.4') contains inconsistent information about the
package id/name/publisher/version
, it means that something went wrong when the package included in your submission was built. In order to
mitigate the issue, you must rebuild the package and submit it again.
If this stage failed with an error message similar to
The App ID '<some-Guid>' is already used for Per-Tenant-Extensions in Business Central and cannot be used for
the AppSource extension with name 'MyApp' and publisher 'MyPublisher'
, this means that there exists one or many PTEs with the same App ID in the service. Since Business Central
doesn't support having AppSource apps and PTEs with the same App ID, it's then recommended to change the
ID of your extension before submitting it in Partner Center. For more information, see Moving a PTE to
AppSource. If the PTEs with that App ID aren't used in any customer environments anymore, you can create a
support case in Partner Center to request an exception.
If this stage failed with the following error message
Automated validation of the submission has failed. Please retry the operation and contact Partner Center
support if it fails again.
, you should create a new submission in Partner Center. If your submission fails again, you should create a
support case in Partner Center as documented in this article.

NOTE
Because the extensions in your submission are validated for each release and country/region targeted by the submissions,
the validation results can be really verbose and cannot always be displayed in their full length in Partner Center. The error
message will then end with ...(Truncated) . If that happens for your submission, you should either enable Azure
Application Insights in your extension, run the self-validation script, or fix the errors visible and iterate on your submission.

My app failed at the "Certification" stage, what do I do next?


At this stage, your extensions are validated to assess whether they meet the requirements defined in the
Marketing Validation Checklist.
Review the Marketing requirements and the Marketing Validation FAQ in order to fix the errors reported.
My app failed at the "Publish application with the service" stage, what do I do next?
At this stage, your extensions are being published to Business Central.
If this stage failed with the following error message
Automated upload to Business Central of the extensions in the submission has failed. Please retry the
operation and contact Partner Center support if it fails again.
, you should create a new submission in Partner Center. If it fails again, you should create a support case in
Partner Center as documented in the dedicated section below.
My app failed at another stage, what do I do next?
If your submission failed at another stage than "Automated application validation", "Certification", or "Publish
application with the service", you should create a support case in Partner Center as documented in the dedicated
section below.

Questions about Azure Application Insights usage during AppSource


submissions
How do I enable Application Insights telemetry for my submissions?
To enable Application Insights signals for your submissions, you must specify the
applicationInsightsConnectionString property in the manifest (app.json) of your extension. For more
information about this property, see JSON files.
I don't see any signals in the resource specified for my extension, what do I do next?
Here's a list of steps that you can follow to troubleshoot this issue:
1. Validate that the Application Insights resource queried is the same one as specified in the manifest (app.json)
of your extension.
2. Validate that the time range when running the query covers the time of the submission.
3. If you're using the applicationInsightsKey property in the manifest (app.json) of your extension, you should
use the applicationInsightsConnectionString property instead because it's more reliable. Make sure to use
the full connection string from your Azure Application Resource.
4. If you're using the applicationInsightsConnectionString property in the manifest (app.json) of your
extension, make sure that you're using the full connection string and that it contains, at least, the following
key-value pairs: InstrumentationKey=<some-key> , IngestionEndpoint=<some-url> , and LiveEndpoint=<some-url>
. For more information, see Connection strings
5. Validate the data sampling and daily cap set for the Azure Application Insights resource. Navigate to the
resource in Azure and go to 'Configure > Usage and estimated costs'. Validate that your Application Insights
retains all data (data sampling is set to 100%) and that you haven't reached your daily cap. For more
information, see Sampling in Application Insights.
I can see some signals in Application Insights, but I can't find why my submission failed, what do I do next?
Much information is provided in the custom dimensions of the signals. The validation errors can generally be
found for the signals with eventId LC0034 . For more information about the signals emitted during the technical
validation of AppSource submission, see Analyzing AppSource Submission Validation Trace Telemetry.

NOTE
Instead of writing your own queries, we recommend using the executable Azure Data Studio Troubleshooting Guide (TSG).
This guide contains queries that will process the signals for your submission and extract the important information.

Questions about developing and maintaining AppSource apps


This section contains frequently asked questions regarding developing apps (in Docker or SaaS). Fore
information, about maintaining apps after they've reached the AppSource marketplace, see Update Lifecycle for
AppSource Apps FAQ.
What does it mean if I have an app in development that needs another dependency loaded, but I can't get
the dependency's codeunits to load in my BC docker instance because it says the dependency's range is
outside my range?
It means that your license doesn't allow you to publish that application. A recommendation would be to either
get a runtime package from the developer of that AppSource app, which will allow you to bypass the licensing
check or to try to test it on an online sandbox environment where that AppSource app is already installed.

Questions about code-signing validation


This section contains frequently asked questions related to the code-signing requirement from the Technical
Validation Checklist. For more information about code-signing, see Sign an APP Package File.
Can I use a self-signed certificate to sign my apps targeting AppSource?
No, it isn't allowed to use a self-signed certificate. The .app package file must be signed using a certificate
purchased from a Certification Authority that has its root certificates in Microsoft Windows. You can obtain a
certificate from a range of certificate providers, including but not limited to GoDaddy, DigiCert, and Symantec.
Do I need to use an EV code -signing certificate to pass the technical validation?
No, it isn't required to use an EV code-signing certificate. Standard code-signing certificates can be used to
satisfy the code-signing requirement.
Can I reuse the same code -signing certificate to sign multiple apps?
Yes, you can reuse the same code-signing certificate for multiple extensions. Code-signing certificates have a
validity period defined over time.

Questions about names, affixes, and ID ranges


In the following, you can read about how affixes and ID ranges are assigned.
Do I need to register different affixes for each of my extensions?
No, you don't need to register affixes for each of your extensions.
The object affixes are registered per publisher so if your apps all have the same publisher, they can share the
same affixes. The automated validation verifies that you're using the three letter affix registered by Microsoft in
your extension, but this still allows you to create longer affixes per extension. For example, if you registered ABC
as your affix, you can use ABCD as the prefix in Extension 1 and ABCE as the prefix in Extension 2. For more
information, see Prefix and suffix for naming in extensions.
Do I need to request a different ID range for each of my extensions?
No, you don't need to request a new ID range for each of your extensions.
The object IDs are registered per partner, not per extension. You can then use a subset of this range for each of
your extensions. It is your responsibility to ensure that you aren't defining objects with the same IDs in different
extensions. If you're doing so, the extensions defining these objects can't be installed together on the same
environment. For more information, see Get Started Building Apps.
Will there be any changes made to the object names character limitation (30 characters) within the near
future?
We would like longer names as well. Introducing namespaces could be one investment. However, such a change
has down-stream breaking impact (any caller needs to qualify calls) and there are SQL constraints on name
lengths for tables, which currently include company name, table name, app ID and needs to be maximum 255.
This is on our long term backlog, but haven't any changes planned soon.

Questions about app identity


This section contains questions related to the identity of apps in AppSource. For more information, see the
questions in App Identity.
When is it okay to change the name of my extension?
Starting from Business Central 2021 release wave 2 (version 19.0), it's possible to change the name of your
extensions without breaking dependent extensions.
When renaming an extension, you must:
increment the version number in the manifest of your extension,
make sure that your submission only targets releases of Business Central starting from 19.0.
update the name of your offer in Partner Center - if your extension is the one for which the offer is created.
When is it okay to change the publisher of my extension?
Starting from Business Central 2021 release wave 2 (version 19.0), it's possible to change the publisher name of
your extensions without breaking dependent extensions.
When changing the publisher of an extension, you must:
increment the version number in the manifest of your extension,
make sure that your submission only targets releases of Business Central starting from 19.0,
contact d365val@microsoft.com in order to register your affixes to your new publisher name.
When is it okay to change the App ID of my extension?

IMPORTANT
The App ID is a critical part of the identity of apps in Business Central, and changing it is a breaking change for all
extensions depending on it. You should then not change the App ID of extensions which are installed for customers in
Business Central Online.

If you are submitting a new version of your extension with a different App ID for an existing offer, then this new
version will be considered as a different extension. This means that all extensions that depend on the extension
with the old app ID must be updated to reference the new App ID. If they are not updated, this will cause issues
such as customer environment upgrade failures which must be fixed within the required time period, see
Maintain AppSource Apps and Per-Tenant Extensions in Business Central Online. Since the app ID is part of how
data is stored in Business Central, this also means that you will have to migrate the data for all customers that
have the extension with the old App ID installed. Note that we do not provide tools for performing data
migration in SaaS, but you can create your own solution to export data from the old extension and re-import
the data after the extension change.
Is it possible to have multiple apps with the same App ID in AppSource?
Each unique codebase has one unique ID. If you have four apps in AppSource, you need to have four unique IDs
for these apps. Otherwise you'll get conflicts.
What if we already have an app on AppSource but we need to create the same app for another country; can
we then have the same app ID for two different apps targeting two different countries?
If they're different apps (different code), they should have different identity. Identity is used in, for example, app
management, dependencies, support cases, and telemetry. If reused across different apps, identity uniqueness is
lost. Another approach could be a common shared (internal/library) app across countries (with one app identity)
and localized functionality as extensions on top (with their own identity).

Questions about Business Central offers


When is it okay to change the offer type of my offer?
There exist two types of offers for Business Central in AppSource: connect apps and add-on apps. It's possible
to change an offer type from connect to add-on by following the steps listed in the dedicated entry below.
However, we don't recommend changing an offer from add-on to connect since it would be a breaking change
for all other extensions depending on the apps in this offer.
For more information about the offer types for Business Central, see App type, contact type, and customer leads.
How to change the offer type from 'connect' app to 'add-on' app?
When changing a connect app to an add-on app, you should:
Navigate to your offer listing in the AppSource marketplace, and copy the URL for your offer
Retrieve the App ID assigned by the service to your offer: the App ID can be found as <appId> in
https://appsource.microsoft.com/en-us/product/dynamics-365-business-central/PUBID.<publisherId>%7CAID.
<offerId>%7CPAPPID.<appId>
Use this App ID in the app.json of the main extension uploaded to your offer

NOTE
The App ID is used as part of the URL of the offer listing and is used as a key to retrieve to customer review left on the
offer listing. Not preserving the App ID means that the offer URL will change and customer reviews will be lost.

How to automatically update my offer using Partner Center submission API?


It is possible to automatically submit apps to AppSource from our DevOps setup by using the Partner Center
Ingestion API. For more information, you can also check this blog post Automatic AppSource Submission of
Business Central apps.

Channels to ask questions or report issues


In the following, you can read about how you reach out for support most efficiently.
When do I contact d365val@microsoft.com?
When registering affixes for your publisher, or adding a new publisher name to your affixes. When contacting
d365val@microsoft.com, make sure to provide the required information documented in Benefits and Guidelines
for using a Prefix or Suffix.
When do I contact Partner Center customer support?
When your submission fails to be successfully completed in Partner Center, but you're experiencing issues
updating your extension(s) to fix the validation errors.

IMPORTANT
If you're using Azure Application Insights, before opening a support case for a failure at the 'Automated application
validation', you must analyze the signals emitted in your Azure Application Insights storage. You can do so by using the
Troubleshooting Guide (TSG). When opening a support case, you must include the Kusto queries you used and the
diagnostic messages that you found. Including the results from the TSG is also recommended.

When do I contact Business Central customer support?


When your submission has been successfully completed in Partner Center, but your customers are experiencing
issues installing or using the app.
When do I log an issue on NavContainerHelper on GitHub?
When you have questions or bugs regarding the self-validation script, or any of the modules exposed by
BcContainerHelper.
For more information, see https://github.com/microsoft/navcontainerhelper/issues.
When do I write on Yammer?
When you have questions on developing and maintaining AppSource apps, on automatically submitting apps to
AppSource, or about the validation process, you can ask a question on Yammer. In this group, you'll find
announcements from Microsoft together with discussions around various AppSource-related articles.
You can join this AppSource group at aka.ms/BCYammer (note that you need to be a Microsoft partner to do so).
If you have problems connecting, email dyn365bep@microsoft.com.

See also
Technical Validation Checklist
Guideline on Creating an Effective Sales Landing
Page for Your App
2/6/2023 • 10 minutes to read • Edit Online

Building a landing page that drives a successful buying transaction


Microsoft will drive qualified traffic to AppSource. Though, once a prospect becomes aware of your app, it will
be your job to guide them through to a successful buying transaction. Deliberately mapping and architecting the
buying journey is critical to ensure a high level of engagement and conversion. Only presenting your app’s
features and functionality, or just providing a free trial, won't ensure prospects will become buyers. For this you
need to have a good landing page that is built to help you capture attention, accelerate your customer
acquisition process, and drive buying behavior. The recommendations on this page will help you do so.

Examples of how other partners have implemented our best practices


To inspire you in creating a good landing page for your app, two of our valued partners, LS Retail and Industry
Built, have offered to provide a sample of what a best practice landing page for a Microsoft Dynamics 365
Business Central partner could look like.
Have a look at their app landing pages and use them as inspiration to build your own landing page:
Industry Built’s Build Food app
LS Retail’s LS Express Start app
In the following checklist, we have “broken down” the elements, on their landing pages in order to showcase
best practices on design and messaging. More specifically, we're looking into layout and structure elements,
content elements, visual elements, anxiety reducing elements and support elements.
Additionally, we have provided specific recommendations on how to apply these elements to help you increase
conversion and maximize the effectiveness of your product’s sales landing page.
We urge you to review and implement these best practices on your landing page – in so doing you'll contribute
in providing the Microsoft community of customers with a consistent buying experience across publishers.

Layout and structure elements


EL EM EN T DESC RIP T IO N EXA M P L E

Company Include the company logo on the page

App name & app logo Include a visual logo of your product
name and a one sentence positioning
statement.

Top menu choices Use clean, straightforward and


descriptive menu options.
EL EM EN T DESC RIP T IO N EXA M P L E

Search box Include a search box so visitors can


quickly find what they're looking for.

Emotional tribal anchor photos Visuals create an emotional Add-


onion. The brain skims over non-
emotional photos.

Visual Make your page easy to scan, with lots


of strong visual imagery.

Logo
The upper-left corner of the landing page is the most valuable section of the entire landing page.
Place your company logo in this location.
If you need help with formulating a positioning statement, try the value proposition generator located at here.
There should ideally be 5 or fewer choices; don't include more than seven options.
The menu text should state what the prospect gains if they select on the menu item
The text should be written from their perspective, not yours.
Recommended menu items:
How to Buy, Benefits Gained, Why Us, and Contact.

The upper-right corner of the page is usually an ideal spot


Faces evoke more emotion than landscapes or machines, and so on.
Include a happy customer that looks similar to your prospect in terms of age, demographic, and industry, and
which shows them dealing with the issues that your prospect can relate to.
Try not to use stock photos of people or objects.
Engagement
Too much text forces the brain to skim, skip, and exit. Text engages the logical, analytical brain, but not the
emotional brain.
Keep it clean and straightforward in terms of design and layout. Use lots of pictures, graphs, and screenshots
to enhance engagement.

Content elements: Text and messaging


EL EM EN T DESC RIP T IO N EXA M P L E

Include a headline question Get your prospects’ attention by “Struggling to manage your ingredient
asking them a compelling pain-based inventory and fretting over allergens?”
question that they can relate to.

You want the prospect to mentally say


“YES” as often as possible and to peak
their curiosity enough to read more.

Your questions should be intriguing


and customer-centric.
EL EM EN T DESC RIP T IO N EXA M P L E

In general, 8 out of 10 people will read


headline copy, but only 2 out of 10 will
read the rest.

Microsoft Dynamics 365 product Somewhere on the landing page, make Insert this paragraph: Microsoft
description sure you include the standard Dynamics 365 Business Central is a
Microsoft Dynamics 365 Business comprehensive business management
Central product description provided solution for small and medium-size
by Microsoft This is a requirement businesses (SMBs) that have outgrown
because your product is adding value their basic accounting software. From
to and building on this foundational day one, this new application makes
solution. ordering, selling, invoicing, and
reporting easier and faster. Dynamics
365 Business Central is deeply
integrated with Microsoft 365 and
includes built-in intelligence, so it's
easy to use and helps users make
better business decisions.

Messaging (Address their pains) Pain is a strong motivator of action.

- - Identify 1-3 key sources of the


client’s most prominent pain early on
the page.

- - Call out the fears that are likely to be


holding them back.

- - Your landing page text and


messaging should predominantly focus
on the pain the prospect is
experiencing, and NOT the features of
your product or service.

Clearly demonstrate to your prospects - Describe the business challenges


that you genuinely understand their they're facing now and the ways their
industry and unique business revenue growth, margins, productivity
problems. and so on, are being negatively
impacted by not taking action now.

EL EM EN T DESC RIP T IO N EXA M P L E

Messaging (Product benefits) Paint a clear, visual and desirable


picture of what is possible.

- Describe the most significant benefits - For example, “Save time and money
and rewards that your prospect will (benefits) by having a system that
realize after purchase. does all the tracking and calculations
for you (features).”

- - Don’t only list features and app


functionality, start with the benefit
first, then you can follow with the
features.
EL EM EN T DESC RIP T IO N EXA M P L E

- - Paint a picture of a possible


experience the prospect will
immediately desire.

- Clearly articulate a compelling desired - If possible, use industry-specific


outcome language and vocabulary to resonate
with your prospect deeply.

- - Choose a particular persona to speak


to directly.

- - Engage prospects by speaking


directly to them using first person
“you” language.

EL EM EN T DESC RIP T IO N EXA M P L E

Messaging (Prove your claims) Include specific calls-to-action on your “Reduce how long it takes to set up
app page. your recipes in the morning from 1
hour to 10 minutes.”

- Don’t make general and abstract -


claims.

- Use data as often as possible to


support your statements.

- If you make specific claims, support


your claims with proof, while
Quantifying impacts and gains.

- The more specific and concrete your


promise of value is, the better.

- Abstract concepts such as “more


efficiency, more productivity, transform
your business” aren't emotionally
impactful or convincing and don't
compel a prospect to act.

Target market - If you support multiple countries or languages, this is a key selling feature. • Find a way to show
this visually.

EL EM EN T DESC RIP T IO N EXA M P L E

Messaging (Compelling call-to- Include specific calls-to-action on your


action) app page

This can be your free trial; a time-limited special price; a scheduled walk-through demonstration; and so on.
The words "free” and “save” are highly emotional words in the English language, so they should be used.
Use bright colors, such as orange, yellow, or red, to call attention to your buttons.
Button text should use benefit language rather than descriptive language.
For example, instead of “Download” write “Click here to start saving money now.”
Try not to send prospects away from your page – always have an embedded next step in your call to action
that brings them back to your landing page.

EL EM EN T DESC RIP T IO N EXA M P L E

Messaging (Create a sense of Help your prospect gain a sense of Your bakery profitability will decrease
urgency by teaching the urgency to buy by teaching them one over the next five years due to an
prospects) thing about how they can be more increase of 3% in the cost of key
efficient or profitable now. inputs, such as wheat and sugar. Want
to know five key strategies that can
help you mitigate this challenge? Click
here to find out how to preserve your
profit margin

Show them how their performance in one key business area is below that of their competitors.
For an example you can provide a quick online self-assessment, a top-10 tips blog post, and much more.
Visual elements

EL EM EN T DESC RIP T IO N EXA M P L E

Pictures (Differentiation Show them, don’t tell them Show the before and after state.
comparison images)

This is a visual image of how your prospects do things now versus how they'll be able to do it in the future.
You aren't telling them but showing them using a visual.

EL EM EN T DESC RIP T IO N EXA M P L E

Compelling proof screenshots Visually demonstrate all the claims that Quickly and easily view inventory
you're making. items.

Graphic dashboards are the most effective method.


Zoom in on the main benefit-related features.
Make sure it's readable, and the benefit is obvious.
Include a caption.
Data should be industry specific so that it resonates with the viewer.
You want prospects to see how their data/process would look in your system.

EL EM EN T DESC RIP T IO N

Videos (Tell your story using videos not text) Include as many videos as possible.

Videos have a much higher level of engagement and viewing time and convey much more than you can ever
say with words.
Include at least one customer testimonial video on your app landing page.
Your client should speak specifically about the pains they had before and the benefits they gained after, not
product features. It should be all about your customers, not you.
Include one product demonstration video.
See the video best practices https://aka.ms/ReadyToGo.
Elements that reduce anxiety and risk, while increasing trust
EL EM EN T DESC RIP T IO N

Customer testimonials Don’t sell your product; let your customers do that for you.

Social proof is more credible and trustworthy to prospects. The purpose of testimonials is to reduce the
buyer's anxiety and fear.
Your testimonials should answer the following questions:
“Will this work for my situation?”
“What benefit will I really get if I buy this?”
“Is this going to be too hard?”
“How long is this going to take?"
“Can I trust this company?”

EL EM EN T DESC RIP T IO N EXA M P L E

Reduce risk Prospects are afraid of being scammed Source: Microsoft.com


and taken advantage of on the
internet. They're naturally cautious and
highly suspect.

You want to convert prospects to buyers.


Make it easy for them to buy, while reducing their anxiety. Transparency is the key to building trust.
Make sure that you include a link to a BUY NOW page, which includes full pricing details.
Give them a compelling offer they can't refuse. Offer a time-limited trial or special pricing discount if they
buy in 30 days.
Use scarcity to compel action. Offer a 100% money-back guarantee.
We recommend providing three offerings, optimized for three different customer segments. For more
recommendations on pricing, see the pricing guide located at https://mbspartner.microsoft.com/BFI/Topic/64

EL EM EN T DESC RIP T IO N

Live chat Include live chat, with a photo of one of your team members
smiling at an appropriate time to increase conversion, such
as when a prospect selects the back button on your pricing
page.

Include their name if possible to build trust.

Support elements: Interactivity and contact options


EL EM EN T DESC RIP T IO N

SHORT lead capture form Include a lead capture form on your page.

Only ask for their name and email address, you can get the rest later.
Your forms shouldn't have more than four or five fields to fill out. You haven't yet earned the right or enough
trust to ask for too much information at this point.
Most lead capture forms are way too long, demanding, and intimidating, and have low completion rates.
NOTE
Nobody has the time or is willing to fill out an annoying form, which is of no value to them, especially if it is purely self-
serving from your standpoint.

EL EM EN T DESC RIP T IO N

Contact Provide prospects with different contact options based on


their readiness to interact with you.

Ideally, include a phone number and an email address with an employee photo.
This alone could double your conversion rate.

EL EM EN T DESC RIP T IO N EXA M P L E

AppSource app page link & social Include a link back to your listing on Return to AppSource.
share AppSource, so the prospect can return
when ready.

Also, enable visitors to share and forward your app with others!

EL EM EN T DESC RIP T IO N

Close them! Add a get star ted button Include a specific call-to-action button with the option to
buy or try.
Get Started with C/SIDE and AL for On-Premises
2/6/2023 • 2 minutes to read • Edit Online

To get started with a mixed development environment of C/SIDE and AL, you must follow the steps below.

Steps to install Business Central on-premises with C/SIDE and AL


development environment
1. Install Business Central on-premises and make sure to include the AL Development Environment .
2. Download Visual Studio Code.
3. From Visual Studio Code, locate Extensions in the left navigation bar, and then choose Install from vsix .
4. Browse to the equivalent folder of
C:\Program Files (x86)\Microsoft Dynamics 365 Business Central\160\AL Development Environment and then
choose Install .
5. Now, press Alt+A, Alt+L to trigger the AL Go! command, choose a project, the target platform, and then
choose Your own ser ver .
6. Authenticate with the credentials you use for signing into Business Central on-premises.
7. In the launch.json file, update the "server": "https://localhost" setting with the URL for server running
Business Central on-premises and save the file.
8. In the app.json file, add the "target": "OnPrem" setting.
9. Now, use the Business Central Administration Console to ensure that the settings on the Development tab
are set as follows:
Allowed Extension Target Level is set to OnPrem .
Enable Developer Ser vice Endpoint checkbox is selected.
Enable Loading Application Symbol References at Ser ver Star tup checkbox is selected.
10. Make sure to read and ensure any additional settings here Running C/SIDE and AL Side-by-Side.

TIP
For information about which sandboxes you can choose, see Sandbox Environments for Dynamics 365 Business Central
Development.

NOTE
Build and get inspired by our sample library on GitHub.

See Also
AL Development Environment
FAQ for Developing in AL
Run C/SIDE and AL Side-by-Side
2/6/2023 • 3 minutes to read • Edit Online

Business Central on-premises supports development using C/SIDE, AL, and Designer side-by-side. When new
objects are added or changed in C/SIDE, these changes must be reflected in the symbol download in Visual
Studio Code using the AL Language extension. To enable this reflection, a command and argument called
generatesymbolreference has been added to finsql.exe and you can run it as illustrated below.

Generate symbols and compile all objects


Open a command prompt, Run as administrator and change to the directory where the finsql.exe file has
been installed as part of Dynamics NAV Development Environment.
Use the generatesymbolreference command specified with the database and server name to add symbol
references to the Object Metadata table for the specified database.
Given the generatesymbolreference command, C/SIDE will traverse all the objects in the database and generate
symbols for them. This command should be run at least once to generate the initial set of symbols to which
incremental updates can be applied.
Syntax example

finsql.exe Command=generatesymbolreference, Database=<DatebaseName>, ServerName=<ServerName>\<Instance>

For example:

finsql.exe Command=generatesymbolreference, Database="Demo Database NAV (11-0)", ServerName=.\NAVDEMO

TIP
The finsql.exe includes several parameters that you can set to suit your environment. For more information, see Using the
Development Environment from the Command Prompt.

This is a lengthy operation. When you run the command, the console returns to an empty command prompt,
and doesn't display or provide any indication about the status of the run. However, the finsql.exe may still be
running in the background. It can take several minutes for the run to complete, and the symbols won't be
generated until such time. You can see whether the finsql.exe is still running by using Task Manager and looking
on the Details tab for finsql.exe .
When the process ends, a file named navcommandresult.txt is saved to the Dynamics NAV Client connected
to Business Central installation folder. If the command succeeded, the file will contain text like
[0] [06/12/17 14:36:17] The command completed successfully in '177' seconds. If the command failed, another
file named naverrorlog.txt will be generated. This file contains details about the error(s) that occurred.
NOTE
The symbol references are stored in the Symbol Reference column of the Object Metadata table of the database. For
on-premises installations, if you experience problems with generating symbols, check the information in the
naverrorlog.txt file. It is also important that the Filter parameter applied to generatesymbolreference command
must refer to Object Metadata fields such as, for example, Object Type or Object ID .

Continuously generate symbols each time you compile objects in


C/SIDE
The generatesymbolreference flag enables incremental symbol generation through the UI or through the
compile command passed on the command line. To update the symbols for a set of objects from the UI, start
C/SIDE with the generatesymbolreference flag, make any desired modifications to your application objects, and
compile them.

NOTE
Use generatesymbolreference set to yes as a command line argument each time you start finsql.exe to have all
compilations add a symbol reference to the Object Metadata table. The default setting of the argument is no.

NOTE
If you make changes in C/SIDE and start the C/SIDE development environment without the generatesymbolreference
flag set to yes , the symbols downloaded from Visual Studio Code will not reflect your changes.

Syntax example

finsql.exe generatesymbolreference=yes

This flag is also a part of the Compile-NavApplicationObject PowerShell command and you can use it to compile
and generate symbols on a filtered set of application objects through PowerShell. This alternative should be
considered if you don't work with the UI in C/SIDE. For more information about it, see Compile-
NavApplicationObject.

Business Central on-premises server setting


In addition to the symbol generation setting you have chosen above, you must enable the Business Central on-
premises server setting.
1. Go to Business Central Administration .
2. Scroll to the Development tab and expand the tab.
3. Choose the Edit button, and then choose the Enable loading application symbols at ser ver star tup
checkbox.

IMPORTANT
This setting must be enabled to allow any symbol generation. If the setting is not enabled, the
generatesymbolreference setting doesn't have any effect.

See Also
Developing Extensions
Create Runtime Packages for Business Central On-
Premises
2/6/2023 • 2 minutes to read • Edit Online

If you want to distribute extensions, you can generate runtime packages that don't contain AL code, but only the
final artifacts used by the server at runtime. Runtime packages thereby allow you to protect the intellectual
property represented by your AL source code.
When the runtime package is generated on the server, the developer license is checked for permissions to the
used extension IDs. The extension in a runtime package can then be installed on servers that don't have a
developer license. The server only needs permissions to run the objects, but not to modify or insert them.

Start using runtime packages


The first step in using runtime packages is to have an extension developed and published to an on-premise
instance. Next, use the following PowerShell command to connect to the server, find the extension, and
download the runtime package.
Get-NavAppRuntimePackage

For more information about this cmdlet, see Get-NAVAppRuntimePackage cmdlet.


The following example gets the NAV App runtime package with the provided name and version.
Get-NAVAppRuntimePackage -ServerInstance DynamicsNAV -AppName 'Proseware SmartApp' -Version 2.3.4.500 -Path
'Prosware SmartApp_2.3.4.500_runtime.app'

For publishing and installing the package, use the Publish-NavApp and the Install-NAVApp PowerShell cmdlets.

Upgrade considerations
Like any extension, extensions distributed in runtime packages will occasionally have to be upgraded so that
they can run on with the latest Business Central version. There are two ways to upgrade a runtime package. Each
way provides a different level of upgrade.
Create a new extension version and runtime package
The recommended way to upgrade a runtime package is to build a new version of the extension against the
latest platform and application. Then, publish the extension to an on-premise instance, and create a new runtime
package version for distribution. Once you have the package, you can then publish it on tenants, and run a data
upgrade like with any other extension.
Recompile the existing package
Another way to upgrade the package is to use the Repair-NAVApp cmdlet to recompile the published package
against the new platform and Business Central server instance. Once complied, you can reinstall the package on
the tenant. Be aware that using the Repair-NAVApp cmdlet doesn't guarantee the extension will work properly.
It's not recommended when upgrading to a new version.
The Repair-NAVApp cmdlet requires that the runtime package includes the source code. You can include the
source code in two different ways:
In the extension's app.json file, set "allowDownloadingSource" or showMyCode to true .
When you run the Get-NavAppRuntimePackage cmdlet, use either the -IncludeSourceInPackageFile $true or
-ShowMyCode $true parameter.

Limitations
The limitation of runtime packages is that they only work for on-premise installations, so you can't submit them
to AppSource. For more information about the extension requirements for AppSource, see Technical Validation
Checklist. Moreover, debugging into an extension to view the source code isn't allowed by default; the
allowDebugging flag is by default set to false . For more information, see Resource Exposure Policy Setting.

NOTE
Runtime packages are guaranteed to work only if published to a platform with the same version as the one where they
were produced.

NOTE
If you set the showMyCode flag to true when running the Get-NavAppRuntimePackage cmdlet, you can enable
debugging and thereby also allow viewing the source code.

See Also
Publish-NAVApp cmdlet
Install-NAVApp cmdlet
JSON Files
2/6/2023 • 20 minutes to read • Edit Online

When you start a new AL project, two JSON files; the app.json file and the launch.json file are generated
automatically. The app.json file contains information about the extension that you're building, such as publisher
information and specifies the minimum version of base application objects that the extension is built on. Often,
the app.json file is referred as the manifest. The launch.json file contains information about the server that
the extension launches on.

NOTE
For information about data migration and creating a migration.json file, see The Migration.json File.

IMPORTANT
The rad.json and the snapshots.json files should not be modified.

App.json file
The following table describes the settings in the app.json file. To see an example app.json file, go to Business
Central Performance Toolkit.

SET T IN G M A N DATO RY VA L UE

id Yes The unique ID of the extension. When


the app.json file is automatically
created, the ID is set to a new GUID
value.
Note: The app ID is used at runtime
to bind table names contained in the
application. Changing the app ID will
result in data from old tables not being
used.

name Yes The unique extension name. The name


can be changed to reflect branding or
acquisition, but then the version
must be incremented.
Note: The name can be used by other
extensions to express a compile-time
dependency on the extension.
Changing the name of your extension
will force any extensions that have
taken a dependency to download
symbols and recompile their extension.
For more information, see App
Identity.
SET T IN G M A N DATO RY VA L UE

publisher Yes The name of your publisher, for


example: NAV Par tner , LLC .
Note: The publisher can be used by
other extensions to express a compile-
time dependency on the extension.
Changing the publisher of your
extension will force those extensions
that have taken a dependency to
download symbols and recompile their
extension. For more information, see
App Identity.

brief No, but required for AppSource Short description of the extension.
submission

description No, but required for AppSource Longer description of the extension.
submission

version Yes The version of the app package.

privacyStatement No, but required for AppSource URL to the privacy statement for the
submission extension.

EULA No, but required for AppSource URL to the license terms for the
submission extension.

help No, but required for AppSource URL to an online description of the
submission extension focusing on the help and
troubleshooting content. The link is
used in AppSource and can be the
same as the value of the
contextSensitiveHelpUrl property.
To learn more about help links, see
Help and Support Links.

url No, but required for AppSource URL of the extension package. The link
submission is used in Business Central, on the
Extension Management page, as
Website . This URL can be a link to an
advertising page for your app, a page
describing the features and additional
resources other than troubleshooting
and help, or it can be a link for
contacting the app support, for
example, see Support Links.

logo No, but required for AppSource Relative path to the app package logo
submission from the root of the package.

test No Version of the dependent test


framework in the format X.Y.U.Z.
Note: This property is only supported
for Business Central version 14 and
earlier, where the base app is C/AL.
SET T IN G M A N DATO RY VA L UE

dependencies No List of dependencies for the extension


package. For example:
"dependencies": [ {"id":
"4805fd15-75a5-46a2-952f-
39c1c4eab821", "name":
"WeatherLibrary", "publisher":
"Microsoft", "version":
"1.0.0.0"},{}]
.
Note: For dependencies to the System
Application and Base Application, these
are no longer listed as explicit
dependencies, but captured in the
application setting as a reference
to the application package. They must
have a version number of the
Application package. See
application below.
Note: The version specified defines the
minimum version for the dependency.
At runtime and when downloading
symbols, the latest version of the
dependency satisfying the specified
name, publisher and, minimum version
will be returned. When runtime is set
to 4.0 or earlier, use appId instead of
id .

screenshots No Relative paths to any screenshots that


should be in the extension package.

platform Yes, if system tables are referenced in The minimum supported version of
the extension the platform symbol package file, for
example: "16.0.0.0". See the Symbols
for the list of object symbols contained
in the platform symbol package file.

application Yes, if base application is referenced in The supported version of the system
the extension. Required for AppSource and base application package file, for
submission example: "16.0.0.0". The file name of
this reference is
Microsoft_Application.app and the
name is Application . If the base
application has been customized, the
Microsoft_Application.app file can be
modified to reference the code-
customized base application instead.
It's important to keep
"name": "Application" in the
extension, but information about
publisher can be changed and the .app
file can be renamed. For more
information, see The
Microsoft_Application.app File.
SET T IN G M A N DATO RY VA L UE

idRange Yes A range for application object IDs. For


example:
"idRange": {"from": 50100,"to":
50149}
. For all objects outside the range, a
compilation error will be raised. When
you create new objects, an ID is
automatically suggested. To learn
about which object ranges are allowed
for your extension, see Object Ranges.

idRanges Yes A list of ranges for application object


IDs. For example:
"idRanges": [{"from":
50100,"to": 50200},{"from":
50202,"to": 50300}]
. For all objects outside the ranges, a
compilation error will be raised. When
you create new objects, an ID is
automatically suggested. You must use
either the idRange or the idRanges
setting. Overlapping ranges aren't
allowed and will result in a compilation
error. To learn about which object
ranges are allowed for your extension,
see Object Ranges.

showMyCode No By default, it's set to false and isn't


visible in the manifest. To enable
viewing the source code when
debugging an extension, add the
following setting:
"showMyCode": true .
Note: This setting will be deprecated
in a future release, and replaced by the
resourceExposurePolicy setting
introduced with runtime 8.0. It's
described in this table.
SET T IN G M A N DATO RY VA L UE

target No By default, this is Cloud . The setting


currently has the following options:
Internal , Extension , OnPrem ,
and Cloud . The Internal and
Extension settings are being
deprecated with runtime 4.0 and
replaced by the OnPrem and Cloud
respectively. For on-premises, you can
set this to OnPrem to get access to
otherwise restricted APIs and .NET
Interop. Then, the Business Central
Server setting must also be set to
OnPrem .
Note: System tables that have the
Scope property set to Internal /
OnPrem can't be accessed from
extensions that have target set to
Cloud / External through direct
reference or through RecordRef. For
more information, see Compilation
Scope Overview

contextSensitiveHelpUrl No, but required for AppSource The URL for the website that displays
submission context-sensitive Help for the objects
in the app, such as
https://mysite.com/documentation/
. If the app doesn't support all locales
currently supported by Business
Central, then include a parameter for
the locale in this URL, /{0}/ , and
also specify the relevant locales in the
supportedLocales setting.

helpBaseUrl No The URL for the website that overtakes


all Help for the specified locales. This
property is intended for localization
apps specifically, since the setting
overwrites the default URL of
/{0}/dynamics365/business-
central
. If you set this value, you must also
specify one or more languages in the
supportedLocales setting.

supportedLocales No The list of locales that are supported in


your Help if different from all locales.
The value on the list is entered into the
URL defined in the
contextSensitiveHelpUrl and
helpBaseUrl properties. The first
locale on the list is default. An example
is
"supportedLocales": ["da-DK",
"en-US"]
for an app that supports only Danish
and English (US).
SET T IN G M A N DATO RY VA L UE

runtime No The version of the runtime that the


project is targeting. The project can be
published to a server that supports
the same or a higher runtime version.
The available options are:
1.0 - Business Central April 2018
Release
2.0 - Business Central Fall '18
Release
3.0 - Business Central Spring '19
Release
4.0 - Business Central 2019 release
wave 2
5.0 - Business Central 2020 release
wave 1
6.0 - Business Central 2020 release
wave 2
6.1 - Business Central 2020 release
wave 2 update 17.1
6.2 - Business Central 2020 release
wave 2 update 17.2
6.3 - Business Central 2020 release
wave 2 update 17.3
6.4 - Business Central 2020 release
wave 2 update 17.4
7.0 - Business Central 2021 release
wave 1
7.1 - Business Central 2021 release
wave 1 update 18.1
7.2 - Business Central 2021 release
wave 1 update 18.3
8.0 - Business Central 2021 release
wave 2
8.1 - Business Central 2021 release
wave 2 update 19.1
9.0 - Business Central 2022 release
wave 1
9.1 - Business Central 2022 release
wave 1 update 20.1
9.2 - Business Central 2022 release
wave 1 update 20.4
10.0 - Business Central 2022 release
wave 2
For more information, see Choosing
Runtime Version in AL.
SET T IN G M A N DATO RY VA L UE

features No Specifies a list of options.

The TranslationFile option


generates a \Translations folder
that is populated with the .xlf file that
contains all the labels, label properties,
and report labels that you're using in
the extension. The GenerateCaptions
option depends on the
TranslationFile setting. It
generates captions for objects that
don't have a Caption or CaptionML
specified. These are then written to the
.xlf file.

The GenerateLockedTranslations
flag is used to generate
<trans-unit> elements in the XLIFF
file for locked labels. The syntax is
"features": [ "TranslationFile",
"GenerateCaptions",
"GenerateLockedTranslations" ]
. For more information, see Working
with Translation Files.

When the NoImplicitWith flag is


specified, ImplicitWith will be
turned off by default. This flag is useful
when all code has been rewritten to
avoid any future use of
ImplicitWith . For more information,
see Pragma ImplicitWith and
Deprecating Explicit and Implicit With
Statements.

internalsVisibleTo No Specifies a list of modules that have


access to the objects that are marked
as Internal using the Access
property from the current module.
The syntax is
{ "appId": "d6c3f231-08d3-4681-
996f-261c06500e1a", "name":
"TheConsumer", "publisher":
"Microsoft"}]
. For more information, see Access
Property and InternalEvent Attribute.
Note: Using internalsVisibleTo in
Business Central online will throw a
warning from AppSourceCop and
PTECop. Access = Internal is not
designed as a security boundary, but
for API development.
SET T IN G M A N DATO RY VA L UE

propagateDependencies No Specifies whether the direct


dependencies of this project should be
propagated as direct dependencies of
projects that depend on this one.
Default is false . If, set to true
then, any dependencies of the current
package will be visible to consumers of
the package. For example, if A depends
on B that depends on C, by default, A
won't be able to use types defined in
C. If B has
"propagateDependencies" : "true" ,
then A will be able to use types
defined in C without taking a direct
dependency.
Note: propagateDependencies
applies to all direct dependencies,
there's no option to exclude specific
dependencies.

preprocessorSymbols No Defines any symbols to use with


preprocessor directives. The syntax is
"preprocessorSymbols": [
"DEBUG","PROD" ]
. For more information, see
Preprocessor Directives in AL.

applicationInsightsKey No, is deprecated in favor of The instrumentation key of the Azure


applicationInsightsConnectionString Application Insights resource for
as of runtime 7.2 - Business Central monitoring operations, for example,
2021 release wave 1 update 18.2 like app secrets retrieval by extensions.

For more information, see Monitoring


and Analyzing Telemetry.

applicationInsightsConnectionString No, but recommended for AppSource The instrumentation key of the Azure
submission Application Insights resource for
monitoring operations, for example,
like app secrets retrieval by extensions.

For more information, see Monitoring


and Analyzing Telemetry.

keyVaultUrls No List of URLs of key vaults that from


which the extension can retrieve
secrets. For example:
"keyVaultUrls":[
"https://myfirstkeyvault.vault.azure.net",
"https://mysecondkeyvault.vault.azure.net"
]
.

For more information, see App Key


Vaults.
SET T IN G M A N DATO RY VA L UE

suppressWarnings No Specifies that warnings issued by, for


example, a specific analyzer rule
shouldn't be shown in the Output
window. Syntax is
"suppressWarnings": [<warning
ID>,<warning ID2>,...]
. For example,
"suppressWarnings": [ "AL0458" ] .
It's also possible to use #pragma
directives for suppressing warnings for
specific areas of code. For more
information, see Pragma Warning
Directive and Suppressing Warnings.

resourceExposurePolicy No Defines the accessibility of the


resources and source code during
different operations. The
resourceExposurePolicy property
contains four options for defining
access: applyToDevExtension ,
allowDebugging ,
allowDownloadingSource , and
includeSourceInSymbolFile . All
defaults are false. The syntax is
"resourceExposurePolicy":
{"applyToDevExtension": true,
"allowDebugging": true,
"allowDownloadingSource": true,
"includeSourceInSymbolFile":
true}
. For more information, see Resource
Exposure Policy Setting.

Launch.json file
The following table describes the settings in the launch.json file. The launch.json file has two configurations
depending on whether the extension is published to a local server or to the cloud.
Publish to local server settings
SET T IN G M A N DATO RY VA L UE

name Yes "Your own server"

type Yes Must be set to "al" . Required by


Visual Studio Code.

request Yes Request type of the configuration. Can


be set to "launch" , "attach" , or
"snapshotInitialize" . Required by
Visual Studio Code. For more
information, see Attach and Debug
Next and Snapshot Debugging.

server Yes The HTTP URL of your server, for


example:
"https://localhost|serverInstance"
SET T IN G M A N DATO RY VA L UE

port No The port assigned to the development


service.

serverInstance Yes The instance name of your server, for


example: "US"

authentication Yes Specifies the server authentication


method and can be set to
"UserPassword" , "Windows" , or
"AAD" . To use AAD authentication for
on-premise servers,
primaryTenantDomain setting must
be entered. For more information, see
Using Azure AD authentication for
Business Central on-premises
installations.

startupObjectType No Specifies whether the object to open


after publishing is a Page type (
"Page" ), a Table type ( "Table" ), a
Report type ( "Report" ) or a Query
type ( "Query" ) object. The default is
"Page" .

startupObjectId No Specifies the ID of the object to open


after publishing. Only objects of type
Page, Table, Report, and Query are
currently supported.

startupCompany No Specifies the name of the company to


open after publishing. If
startupCompany is specified, the
settings startupObjectId and
startupObjectType must also be
defined.

schemaUpdateMode No Specifies the data synchronization


mode when you publish an extension
to the development server, for
example:
"schemaUpdateMode": "Recreate"
The default value is Synchronize. For
more information, see Retaining table
data after publishing
This feature is not supported in
Dynamics NAV.

environmentType No Specifies which type of environment to


use to connect to Business Central.
Possible values are OnPrem , Sandbox
, or Production .

environmentName No Specifies which named production or


sandbox environment to use in cases
where multiple sandboxes are owned
by the same tenant.
SET T IN G M A N DATO RY VA L UE

breakOnError No Specifies if and how the debugger


breaks on errors in Try functions. With
Business Central 2022 release wave 2
breakOnError contains the following
options: true false , None , All ,
ExcludeTry .
false/None - does not break on any
errors, true/All -breaks on all
errors, and ExcludeTry - breaks on
errors only if they occur outside of the
context of a Try function.
The values true and false are
retained for now for backwards
compatibility. They map to All and
None . We recommend using the
latter going forward. True and
false might become obsolete in a
future version.

breakOnNext No Specifies the session type that the


server will connect to. The options are:
WebserviceClient - web API-based
client including ODdata and SOAP
clients,
WebClient - standard web client,
Background - background sessions,
such as job queues, see Task Scheduler.

This setting applies to Attach and


Debug Next and to Snapshot
Debugging.

For Attach debugging, breakOnNext


defines the next client session that the
debug engine will attach to for the
same user who has initiated an attach
debug session from Visual Studio
Code.

For Snapshot debugging,


breakOnNext defines the next session
to hook AL code execution recording
for a given user on a tenant. Or, if this
isn't specified with the userId in the
configuration settings; the first user on
the tenant.
SET T IN G M A N DATO RY VA L UE

breakOnRecordWrite No Specifies if and how the debugger


breaks on record changes. With
Business Central 2022 release wave 2
breakOnRecordWrite contains the
following options: true , false ,
None , All , and
Exclude Temporary .
- false / None specifies to not break
on any record writes.
- true / All specifies to break on all
record writes.
- ExcludeTemporary specifies to
break on record writes only if they are
not on a temporary table.

The values true and false are


retained for backward compatibility,
mapping to All and None . It's
recommended using the latter going
forward. True and false might
become obsolete in a future version.

launchBrowser No Specifies whether to open a new tab


page in the browser when publishing
the AL extension (Ctrl+F5). The default
value is false . If the value isn't
specified or set to true , the session
is started. If the value is explicitly set to
false , the session isn't started
unless you launch your extension in
debugging mode.

enableSqlInformationDebugger Yes Specifies whether the debugger shows


the SQL information. The default value
is true . For more information, see
Debugging SQL behavior.

enableLongRunningSqlStatements Yes Specifies whether the debugger


enables long running SQL statements
in the debugger window.

longRunningSqlStatementsThreshold Yes Sets the number of milliseconds spent


before a SQL statement is considered
as long running in the debugger.

numberOfSqlStatements Yes Sets the number of SQL statements to


be shown in the debugger.
SET T IN G M A N DATO RY VA L UE

dependencyPublishingOption No Available options are:


Default - set dependency publishing
will be applied
Ignore - dependency publishing is
ignored
Strict - dependency publishing will
fail if there are any apps that directly
depend on the startup project and
these apps aren't part of the
workspace. For more information, see
Working with multiple projects and
project references.

disableHttpRequestTimeout No Specifies if the default setting for HTTP


request timeout in Visual Studio Code
is switched off. The default value is
false . If the value is set to true
requests can run without timeout.

attach No Sets the session to attach to. There are


two options;
Attach to the next client on the
cloud sandbox
and
Attach to the next client on
your server
. Use the first option to attach to a
cloud session, and the second option
to attach to a local server. For more
information, see Attach and Debug
Next.

forceUpgrade No Always run upgrade codeunits, even if


the version number of the extension is
the same as an already installed
version. This can be useful for
troubleshooting upgrade issues.

Note: The forceUpgrade setting


requires the package ID to be
changed.

useSystemSession No Runs install and upgrade codeunits in


a system session. This will prevent
debugging install and upgrade
codeunits.

snapshotFileName No Specifies the snapshot file name used


when snapshot debugging files are
saved. For more information, see
Snapshot Debugging.

primaryTenantDomain No Specifies the URL of the Azure AD


organization or company associated
with the Azure AD tenant. This setting
enables AAD scenarios for on-premises
installations. For more information, see
Azure AD authentication for Business
Central on-premises
SET T IN G M A N DATO RY VA L UE

Publish to cloud settings


SET T IN G M A N DATO RY VA L UE

name Yes "Microsoft cloud sandbox"

type Yes Must be set to "al" . Required by


Visual Studio Code.

request Yes Request type of the configuration.


Must be set to "launch" . Required
by Visual Studio Code.

startupObjectType No Specifies whether the object to open


after publishing is a Page type (
"Page" ), a Table type ( "Table" ), a
Report type ( "Report" ) or a Query
type ( "Query" ) object. The default is
"Page" .

startupObjectId No Specifies the ID of the object to open


after publishing. Only objects of type
Page, Table, Report and Query are
currently supported.

startupCompany No Specifies the name of the company to


open after publishing. If
startupCompany is specified, the
settings startupObjectId and
startupObjectType must also be
defined.

tenant No Specifies the tenant to which the


package is deployed. If you specify
multiple configurations, a drop-down
of options will be available when you
deploy. This parameter must contain a
tenant AAD domain name, for example
mycustomer.onmicrosoft.com .

environmentType No Specifies which type of environment to


use to connect to Business Central.
Possible values are OnPrem , Sandbox
, or Production .

environmentName No Specifies which named production or


sandbox environment to use in cases
where multiple sandboxes are owned
by the same tenant.

applicationFamily No (Yes for Embed apps) The application family in the cloud
server, for example Fabrikam . This
property is reserved for Embed apps.
SET T IN G M A N DATO RY VA L UE

breakOnError No Specifies if and how the debugger


breaks on errors in Try functions. With
Business Central 2022 release wave 2
breakOnError contains the following
options: true , false , None , All ,
ExcludeTry .
false/None - does not break on any
errors, true/All -breaks on all
errors, and ExcludeTry - breaks on
errors only if they occur outside of the
context of a Try function.
The values true and false are
retained for now for backwards
compatibility. They map to All and
None . We recommend using the
latter going forward. True and
false might become obsolete in a
future version.

breakOnNext No Specifies the session type that the


server will connect to. The options are:
WebserviceClient - web API-based
client including OData and SOAP
clients,
WebClient - standard web client,
Background - background sessions,
such as job queues, see Task Scheduler.

This setting applies to Attach and


Debug Next and to Snapshot
Debugging.

For Attach debugging, breakOnNext


defines the next client session that the
debug engine will attach to for the
same user who has initiated an attach
debug session from Visual Studio
Code.

For Snapshot debugging,


breakOnNext defines the next session
to hook AL code execution recording
for a given user on a tenant. Or, if this
isn't specified with the userId in the
configuration settings; the first user on
the tenant.
SET T IN G M A N DATO RY VA L UE

breakOnRecordWrite No Specifies if and how the debugger


breaks on record changes. With
Business Central 2022 release wave 2
breakOnRecordWrite contains the
following options: true , false ,
None , All , and
Exclude Temporary .
- false / None specifies to not break
on any record writes.
- true / All specifies to break on all
record writes.
- ExcludeTemporary specifies to
break on record writes only if they are
not on a temporary table.

The values true and false are


retained for backward compatibility,
mapping to All and None . It's
recommended using the latter going
forward. True and false might
become obsolete in a future version.

launchBrowser No Specifies whether to open a new tab


page in the browser when publishing
the AL extension (Ctrl+F5). The default
value is false . If the value isn't
specified or set to true , the session
is started. If the value is explicitly set to
false , the session isn't started
unless you launch your extension in
debugging mode.

enableSqlInformationDebugger Yes Specifies whether the debugger shows


the SQL information. The default value
is true . For more information, see
Debugging SQL behavior.

enableLongRunningSqlStatements Yes Specifies whether the debugger


enables long running SQL statements
in the debugger window.

longRunningSqlStatementsThreshold Yes Sets the number of milliseconds spent


before a SQL statement is considered
as long running in the debugger.

numberOfSqlStatements Yes Sets the number of SQL statements to


be shown in the debugger.
SET T IN G M A N DATO RY VA L UE

dependencyPublishingOption No Available options are:


Default - set dependency publishing
will be applied
Ignore - dependency publishing is
ignored
Strict - dependency publishing will
fail if there are any apps that directly
depend on the startup project and
these apps aren't part of the
workspace. For more information, see
Working with multiple projects and
project references.

disableHttpRequestTimeout No Specifies if the default setting for HTTP


request timeout in Visual Studio Code
is switched off. The default value is
false . If the value is set to true
requests can run without timeout.

attach No Sets the session to attach to. There are


two options;
Attach to the next client on the
cloud sandbox
and
Attach to the next client on
your server
. Use the first option to attach to a
cloud session, and the second option
to attach to a local server. For more
information, see Attach and Debug
Next.

Global and workspace launch configuration


With Business Central version 21.1, you can add a launch property to a code-workspace or in the settings.json
file. This allows for a centralized configuration of projects. A local launch.json file overrides the workspace and
global configuration. A workspace launch configuration overrides the launch configuration specified in the
global settings.json file.

NOTE
If a local launch.json file doesn't contain a valid AL launch configuration, we'll try to find one in the code-workspace
first, and then in the settings.json files. However, if the launch property is specified in the code-workspace file even
without specifying a valid AL configuration, the global settings.json file won't be able to override it.

See Also
AL Development Environment
App Identity
Debugging in AL
Resource Exposure Policy Setting
AL Language Extension Configuration
Configure Context-Sensitive Help
App Key Vaults
The Migration.json File
2/6/2023 • 2 minutes to read • Edit Online

INTRODUCED IN: Business Central 2019 Release Wave 2, update 15.3, for on-premises only

Data migration allows you to move table and field data between extensions. The migration.json file provides a
pointer to the ID of an app that one or more tables will be moved to. This file allows you to move table and field
data from, for example, a code-customization on the base application to an extension of the base application.
The migration.json file can be added into the app project of an extension that a table is moved from to specify
the ID of the app that the table will be moved to. It can, for example, be placed at the root of the AL project. The
migration.json file must be created manually by following the steps and syntax as described below.

In the extension app.json file, ensure that "target": "OnPrem" . For more information, see JSON Files.

Create the migration.json file


1. In the root folder of the app project that will migrate data to a different app project, choose New File .
2. Name the file migration.json .
3. Edit the file by adding one or more IDs inside the "apprules":[] section, such as:

{
"apprules": [
{
"id": "12345678-abcd-abcd-abcd-1234567890ab"
}
]
}

4. Save the migration.json file in the project.


You now have the migration file in place for the data migration from one app project to another. The migration
file will be used for performing the data migration steps. For more information, see Migrating Tables and Fields
Between Extensions.

See Also
JSON Files
Migrating Tables and Fields Between Extensions
AL Language Extension Configuration
2/6/2023 • 4 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

The AL Language extension has many settings that can be defined for a specific user or for a workspace. To
activate the settings, press Ctrl+Shift+P , and then choose Preferences: Open Settings (UI) for workspace
settings, or choose Preferences: Open User Settings for user settings. Under Extensions , and AL
Language extension configuration , you'll find the settings that are available for the AL Language extension.
For tips on how to optimize Visual Studio Code, see Optimizing Visual Studio Code for AL Development.

Settings
The following table describes the user and workspace settings for the AL Language extension:

SET T IN G VA L UE

Assembly Probing Paths Sets the list of directory paths where the compiler searches
for referenced .NET assemblies. For example:
"al.assemblyProbingPaths": ["./.netpackages",
"C:/Program Files/Assemblies"]

Are Profile Lenses Supported Enables the Profiler CodeLens for AL, default value is true .
Syntax is "al.areProfileLensesSupported": true . For
more information, see AL Profiler Overview.

Browser Specifies the browser in which to open the Business Central


client when launching the application from Visual Studio
Code.

Background Code Analysis Specifies whether the code analysis should be performed in
the background.

Code Analyzers Sets the list of paths to code analyzers to use for performing
code analysis. For example:
"al.codeAnalyzers": ["${AppSourceCop}",
"${CodeCop}"]
.
SET T IN G VA L UE

Compilation Options Specifies the compilation options;


continueBuildOnError - specifies if build should continue
even if errors are found. The default and recommended
value from a performance point of view is false . Set the
value to true to continue building the project, even if
errors are found. It requires al.incrementalBuild to be
false .
delayAfterLastDocumentChange - specifies the number of
milliseconds to wait after the last buffer changes before
getting document diagnostics. After changing the value of
this option, you must restart Visual Studio Code for it to
take effect. Default value is 800 .
delayAfterLastProjectChange - specifies the number of
milliseconds to wait after the last buffer changes before
getting complete diagnostics. After changing the value of
this option, you must restart Visual Studio Code for it to
take effect. Default value is 4000 .
maxDegreeOfParallelism - specifies the maximum number
of concurrent tasks the compiler should use when compiling
the project. Default value is 2 .
parallel - controls whether to use concurrent builds.
Default value is true .
generateReportLayout - controls whether the compiler will
generate Report Layout files when building the package.
Default value is true .

Editor Services Log Level Sets the logging verbosity level for the AL Language Editor
Services host executable. Possible values are Verbose ,
Normal , Warning , and Error .

Editor Services Path Specifies the path to the Editor Services host executable.

Enable Code Actions Specifies whether code actions should be enabled for all
source files in the current project. Default is false .

Enable Code Analysis Specifies whether code analysis should be performed for all
source files in the current project. Default is false . If this is
set to true , you must specify the Code Analyzers setting
with the list of code analyzers to use.

Enable Script IntelliSense Specifies whether IntelliSense should be enabled for control
add-in script files. Turn this off, if it interferes with advanced
JavaScript or TypeScript configurations. Default is true .

Incognito Specifies whether to open the browser in Incognito/InPrivate


mode when launching the application from Visual Studio
Code. This option will take effect only if the Browser option
is set to a non-default value.
SET T IN G VA L UE

Incremental Build Specifies whether a project, when it's built using


Ctrl+Shift+B , Ctrl+F5 , or F5 , will reuse the last known
tracked compilation, which will enhance the compilation time
significantly. For more information about project to project
references, see Working with multiple projects and project
references.
Note: Setting this to true won't do an end-to-end build,
as it's depending on an already-compiled state. To get a
clean, full build, this flag must be set to false . Default is
false .
Impor tant: If this setting is enabled, then all translations
will be ignored, even though the
"features": [ "TranslationFile" ] setting is specified
in the app.json file. For more information, see Working
with Translation Files.

Package Cache Path Sets the directory path where reference symbol packages are
located.

Profiler Colors Specifies the colors used to define the application types in
the profiler output. Accepts valid color names, hex codes,
and rgba() values. The properties are systemApplication -
default color green , baseApplication - default color
magenta , and extension - default color yellow .

Rule Set Path Sets the path to the file containing the customized rules to
use when running code analysis.

Snapshot Debugger Lines Hit Decoration Specifies the decoration values for a line that is hit by the
snapshot debugger. Syntax is
al.snapshotDebuggerLinesHitDecoration .

Snapshot Debugging Path Sets the directory path where the snapshot debugger
sources are located. Default is ./.snapshot .

Snapshot Output Path Sets the directory path where snapshot files are saved.
Default is ./.snapshots .

Statement Lens Minimum Sets the lower limit for the time spent on statement
execution expressed in milliseconds. Default value is 500 .
Syntax is "al.statementLensMin": 100 . For more
information, see AL Profiler Overview.

Use Legacy Runtime Use the .NET Framework runtime for hosting the language
service instead of the .NET Core runtime. Enabling this might
result in a reduced level of performance.

Enable Fast IntelliSense Completion Autocomplete in IntelliSense using autocomplete characters


such as period and parentheses. Syntax is
al.enableFastIntelliSenseCompletion . The list of
characters that can be used is: period, comma, colon,
semicolon, brackets, and single and double quotes. Default
value is switched off.
SET T IN G VA L UE

Generate PermissionSet for Extension Objects Generate a permission set as an AL object. Syntax is
al.generatePermissionSetForExtensionObjects . When
invoking the command, the developer can choose to create
a new permission file or select an existing file to update.

See Also
AL Development Environment
Debugging in AL
JSON Files
Working with multiple projects and project references
Resource Exposure Policy Setting
2/6/2023 • 7 minutes to read • Edit Online

CHANGED IN: Business Central 2022 release wave 2

When you develop an extension, your code is protected against downloading or debugging by default. Read
below about adding Intellectual Property (IP) protection against downloading or debugging into an extension to
see the source code in the extensions.
The extension development package provides a pre-configured setting for protection against viewing or
downloading the code of the extensions. However, this setting can also be controlled in the manifest; the
app.json file.

The properties of the resource exposure policy


NOTE
With Business Central 2021 release wave 2, the ShowMyCode setting has been replaced by the
resourceExposurePolicy setting which offers a richer access control. The ShowMyCode will be deprecated in a future
release and can't be used together with the resourceExposurePolicy setting. If ShowMyCode is set, default values for
resourceExposurePolicy will be applied ( false ).

When you start a new project, an app.json file is generated automatically, which contains the information
about the extension that you're building. In the app.json file, you can specify a setting called
resourceExposurePolicy that defines the accessibility of the resources and source code during different
operations. resourceExposurePolicy specifies the following list of options: applyToDevExtension , allowDebugging ,
allowDownloadingSource , and includeSourceInSymbolFile . Each of these properties defines the specific areas in
which the source code of an extension can be accessed. All of the options are by default set to false , which
means that by default, no dependent extension can debug or download the source code of your extension. The
syntax of the resourceExposurePolicy setting is as follows:

`"resourceExposurePolicy": {"applyToDevExtension": <boolean>, "allowDebugging": <boolean>,


"allowDownloadingSource": <boolean>, "includeSourceInSymbolFile": <boolean>}`

NOTE
The resourceExposurePolicy setting isn't visible in the app.json file when it's generated. If you want to change the
default value from false , you must add the setting as shown in the syntax example above. You can always override this
for your AppSource aåå or per-tenant extension by changing the setting.

IMPORTANT
The AL: Go! template sets the allowDebugging , allowDownloadingSource , and includeSourceInSymbolFile
options in the resourceExposurePolicy setting to true .

applyToDevExtension
APPLIES TO: Business Central 2022 release wave 2 and later

With the applyToDevExtension flag, you can specify if all resource exposure policies specified for the extension
also apply to developer extensions, by setting the value to true .
allowDebugging
To allow debugging into your extension, you must set the allowDebugging flag when the extension is taken as a
dependency, otherwise debugging isn't allowed. The default value of allowDebugging is false .
If you want to allow debugging into your extension to view the source code, the allowDebugging property in the
app.json file must be set to true . For example, if someone develops an extension A and another person
develops an extension B, where B depends on A, then debugging B will only step into the code for A, if a method
from A is called and if the allowDebugging flag is set to true in the app.json file for extension A as shown in
the example below. By adding this setting, you enable debugging into an extension to view the source code and
variables when that extension is set as a dependency.

`"resourceExposurePolicy": {"allowDebugging": true}`

NOTE
allowDebugging doesn't apply to Profiles, Page Customizations and Views, because these objects can't define any
custom logic in procedures or triggers. The code for Profiles, Page Customizations, and Views defined in an extension with
allowDebugging set to false can still be accessed and copied using Designer.

The [NonDebuggable] attribute


Unless, you've specified the [NonDebuggable] attribute on methods and variables, setting the allowDebugging to
true will allow stepping into this code. If you, however, have marked the methods and variables with the
[NonDebuggable] attribute, these methods and variables will remain non-debuggable. For more information, see
NonDebuggable Attribute.
When should I set allowDebugging to true ?
The default value of the allowDebugging flag is false . If allowDebugging is set to true , anyone who extends
your code can debug it.
It's, however, not possible to allow both, debugging and Go to Definition , and still protect source from being
extracted through the debug experience, for example, by using third party Visual Studio Code tools. For
AppSource apps, if you want to protect your IP, it's recommended to limit access to the source by setting the
resourceExposurePolicy flags to false . Then rely on the ability to grant yourself and optionally trusted reseller
partners time-limited individual access through the dynamic override of the resource policy. For more
information, see Override the resource policy in this article.
For per-tenant extensions, if the customer owns the IP and approves of exposing it, it's recommended to at least
allow debugging and include source in symbols to make troubleshooting, extracting IP from the service, and
working across resellers easier.
When can code be viewed even though the allowDebugging flag is set to false ?
Someone will still be able to view your code if an extension is deployed through Visual Studio Code as a DEV
extension , as opposed to deployed using a cmdlet, by using the Extension Management page in Business
Central or via AppSource. Use the applyToDevExtension setting to specify if all resource exposure policies should
also apply to your DEV extension .
allowDownloadingSource
When this flag is set to true in the app.json file of extension A, the source code and any media files of
extension A can be downloaded, for example, from the Download Source option in the Extension
Management page in Business Central. Extension A can be a PTE or a DEV extension. The default value of
allowDownloadingSource is false .

includeSourceInSymbolFile
When this flag is set to true in the app.json file of extension A, the downloaded symbol file in Visual Studio
Code, which is accessed by using the Downloading Symbols functionality, contains symbols, source code, and
all other resources of extension A. When includeSourceInSymbolFile is set to false , the source isn't available in
the symbol files, and you can't use Go to Definition to view source. You can, however, still extend, get
IntelliSense for, and call functionality in extension A by relying on its exposed symbols and signatures. The
default value of includesourceInSymbolFile is false .
Example JSON file
Example JSON file with default values when generated by using the AL: Go! command.

...
"resourceExposurePolicy": {
"allowDebugging": true,
"allowDownloadingSource": false,
"includeSourceInSymbolFile": false
},
"runtime": "8.0",
"keyVaultUrls": [
"https://mykeyvault.vault.azure.net"
],
"applicationInsightsConnectionString": "MyConnectionString1234"
...

Override the resource policy


The resource exposure override can be used to dynamically grant access to the users. Overriding the policy is
useful, if you've, for example, set the allowDebugging flag to false in your app.json file, but you want to allow
specific Azure AD tenants access temporarily. If you don't specify anything in the
BC-ResourceExposurePolicy-Overrides secret described below, then no one can debug your code if
allowDebugging is set to false . On the contrary, if you've set allowDebugging to true in your app.json file,
then it doesn't matter what you specify in the BC-ResourceExposurePolicy-Overrides secret, anyone will be able to
debug into that code.
Requirements for overriding the resource policy
It's a requirement to enable overriding the resource policy, that you have a key vault set up. Setting up a key
vault is an onboarding process that is described in the links below. Follow the guidelines for keeping your key
vault safe. If the key vault is used for multiple purposes, you can create different policies for access to override
the secret in the key vault.

NOTE
Remember to register all apps that should access your key vaults, it's not enough to just add the key vault setting to your
app.json manifest files.
IMPORTANT
Resource exposure policy overrides can be used to dynamically grant users of a given AAD tenant ID access. The users
performing the action, such as debugging, can be delegated admins or a guest user on the target environment. In
addition, you must specify the tenant property in the launch.json file. The tenant property must be set to the
target tenant ID. For more information, see JSON Files.

For more information, see Using Key Vault Secrets in Business Central Extensions and Setting up App Key Vaults
for Business Central Online. For Business Central online, the app key vault feature is only supported for
AppSource extensions.
The BC-ResourceExposurePolicy-Overrides secret
Once the key vault is set up, the policy of an extension can be overridden by using settings in your extension's
key vault. A secret named BC-ResourceExposurePolicy-Overrides must be added to the key vault. The value of the
secret is a .json file with the structure as shown in the example below. Because the json secret value in this case
spans multiple lines, you must use Azure PowerShell instead of the Azure portal to define the json secret value.
To enable one or more of the properties for use by an Azure AD tenant, you must add the tenant ID to enable
that property for the users of the tenant. Doing so enables a temporary access to the source code, for example,
for debugging purposes.

$json = '{
"allowDebugging": [
"9e2b6561-1ba6-4790-abcc-c84abf9a8961"
],
"allowDownloadingSource": [
"9e2b6561-1ba6-4790-abcc-c84abf9a8961"
],
"includeSourceInSymbolFile": [
"9e2b6561-1ba6-4790-abcc-c84abf9a8961"
]
}'
$Secret = ConvertTo-SecureString -String $json -AsPlainText -Force
Set-AzKeyVaultSecret -VaultName "YourKeyVaultName" -Name "BC-ResourceExposurePolicy-Overrides" -SecretValue
$Secret

NOTE
If debugging is enabled dynamically, a breakpoint can be set in the protected source code when the debugging session is
started.

Partner telemetry
If you specify the applicationInsightsConnectionString setting for your extension in the app.json file, it enables
a signal to be sent every time the policy is read from the key vault whenever, there's an issue with reading the
policy, or an issue with parsing the JSON. For more information, see Sending Extension Telemetry to Azure
Application Insights.

"applicationInsightsConnectionString": "MyConnectionString1234"

See Also
JSON Files
AL Development Environment
NonDebuggable Attribute
Develop for Multiple Platform Versions
2/6/2023 • 2 minutes to read • Edit Online

The AL language extension is compatible with multiple platform versions. You can install the AL Language
extension from the Visual Studio Code marketplace and use it to develop solutions for Dynamics 365 Business
Central.

Define the platform version


To set the platform version, add the runtime property in the app.json file. This attribute defines the platform
version that the extension is targeting. Depending on the platform version, some features become available,
while some features aren't supported. For example, OData-bound actions can only be used when the platform
version is 2.0 or higher.

NOTE
The AL Language extension isn't compatible with Dynamics NAV 2018 version backwards. For Dynamics NAV 2018
development, the traditional method should be used. You must install the Visual Studio Code extension from the
ALLanguage.vsix file shipped on the DVD.

Version compatibility
The following two elements are compared when you publish an extension.
1. The runtime version of the extension defined in the app.json file.
2. The runtime version of the platform that the extension is targeting.
In the app.json file, set the extension runtime version lower than the platform version. When you set the
extension to a higher runtime version, the extension package may contain certain features that the platform
may not support which would result in an error. Therefore, you must lower the extension runtime version than
the one that platform supports in order to publish your extension.
Things to be aware of
1. An error will be thrown when you publish an extension with a higher runtime version than the one that
platform supports. For example, if you set the runtime value to 2.0 , you get the following error
message.
The runtime version of the extension package is currently set to '2.0'. The runtime version must be
set to '1.0' or earlier in the app.json file in order to install the extension package on this
platform.

2. When you lower the extension runtime version, you may get warnings about the newest features not
supported by the earlier versions of the platform.
3. A best-effort compilation is made when you publish an extension compiled with a lower runtime version.
This is allowed in order to avoid recompilation of the extension package every time you upgrade the
platform.

See Also
Debugging in AL
Developing Extensions
Microsoft .NET Interoperability from AL
Optimize Visual Studio Code for AL Development
2/6/2023 • 2 minutes to read • Edit Online

Visual Studio Code is built to handle many smaller dependent projects instead of one large project. However, as
the base application isn't yet split into modules or components that allow managing the code in smaller projects,
we recommend the following performance optimizations.
Open your settings.json file in the project (or global settings if you prefer that) pressing Ctrl+Shift+P . Set:
"al.enableCodeAnalysis": false to turn off code analysis completely, read more here Using the Code
Analysis Tool.
"al.backgroundCodeAnalysis": false to turn off running code analysis in the background, but code
analysis will be enabled when building with Ctrl+Shift+B . This is an alternative if analyzers are required
with "al.enableCodeAnalysis": true .
"al.enableCodeActions": false to turn off AL Code Actions, read more here AL Code Actions.
"al.incrementalBuild": true to allow the compiler to reuse the existing background compilation for
creating the package.
"editor.codeLens": false to turn off code lens in Visual Studio Code, see Code Navigation.
"[al]": {"editor.formatOnSave": false } to turn off formatting when saving a file for AL. If you still want
formatting, then you can adjust what to run formatting on, and you can choose modifications by using
the Format On Save Mode option.
Add the build folder to the exclusion list for Windows Defender.

See also
Development in AL
Best Practices for AL
Work with multiple AL project folders within one
workspace
2/6/2023 • 2 minutes to read • Edit Online

Visual Studio Code offers the multi-root workspace feature, which enables grouping different project folders
into one workspace. The AL Language extension also supports the multi-root functionality and allows you to
work with multiple AL folders including roots and projects within one workspace.

Work with multiple project folders


Go through the following steps to work simultaneously on several related projects.
1. On the File tab of Visual Studio Code, choose Add Folder to Workspace... .
2. Save the workspace file if you plan to open it again.
This will create a code-workspace file that contains an array of folders with either absolute or relative paths. If
you want to share your workspace files, choose the relative paths.
3. Modify the settings of your files in the Settings editor. You can change your user settings, global workspace
settings, or individual folder settings.
For more information about multi-root workspaces in Visual Studio Code, see Multi-root Workspaces.

Group a set of disparate project folders into one workspace


It isn't mandatory to use only AL-based roots. Different kinds of projects can be mixed, and each AL project will
have its configuration values for the following settings:
al.packageCachePath
al.enableCodeAnalysis

The al.packageCachePath setting allows you to specify the path to a folder that will act as the cache for the
symbol files used by your project. It can be specified in the User Settings , Workspace Settings , or Project
Settings . The al.enableCodeAnalysis setting allows you to enable the execution of code analyzers on your
project. It can likewise be specified in the User Settings , Workspace Settings , or Project Settings . For more
information, see AL Language Extension Configuration.

Making sure that your project or workspace is updated


NOTE
When working in a project or workspace, some operations require that you run a Reload Window command (Ctrl+R)
for your project or workspace to ensure that it’s updated correctly. Examples are; source control operations like Git Pull,
changes made to the app.json file, or updating User or Workspace settings for AL.

See also
Development in AL
Best Practices for AL
Working with Multiple Projects and Project References
Work with multiple projects and project references
2/6/2023 • 6 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

A project reference in an AL-based workspace is defined as a dependency in the app.json file and exists as a
project in the workspace. There's no special visual representation of a project reference.

IMPORTANT
A project reference is the full id , name , publisher , and version of an existing project in the workspace. This is
contrary to an application reference where it is enough to specify a minimal version. If you're using workspaces with
multiple projects and change the name or publisher of an extension in the workspace, the dependencies in the
app.json file must be updated with the new name and publisher or you may encounter issues with reference resolution.
For more information, see App Identity.

In the example below, the project called Leaf defines two dependencies to the projects Middle and Root . Since,
both Root and Middle are projects in the workspace they're considered project references.

The advantage of working with project references is that there's no need to download the symbols for a project
reference. They're there as the symbols for the reference project and will be resolved as they're modified. For
example, if you add a new method to a codeunit in the Root project and reference the codeunit in the Leaf
project, the method will automatically resolve as you touch the Leaf project.
When a project is built with Ctrl+Shift+B , the following will happen:
1. The .app file is copied to the .alpackages folder of all projects that depend on it.
2. All project references that might be "dirty" are also built.

NOTE
If reference resolution stops working then building the project reference and re-initializing the workspace using Reload
Window resolves references.

Project loading in a workspace


As a project loads in a workspace, it will attempt to load all its project references as a transitive operation. While
a project loads, features like IntelliSense and hover over aren't available. Depending on the number of project
references and files in the project, this operation can be time consuming.
When the project loads in the workspace, the user is notified with the standard Visual Studio Code progress
notification dialogs of the current state. The notifications can be closed, but they won't stop loading a project. If
the user selects somewhere else or changes the active project, loading of the previous project will be canceled
and the newly selected active project will start loading instead. A project can be loaded by making it active, by
opening an .al file, or opening the app.json project file. Once a project is loaded it stays loaded until the AL
language server is active, or the Reload Window command, using Ctrl+R is triggered.
Projects that haven't been loaded in the workspace are decorated with the letter N .

Publish changes
With the introduction of project references, the publishing logic in a workspace has changed. Publishing, either
with Ctrl+F5 or RAD publishing using Alt+Ctrl+F5 , will do a set publishing of all the projects that have
changed with defining a startup project. The startup project is always the active project.
A project is considered changed if any of its application objects have changed in the sense that the application
object is already in the rad.json or will be in the rad.json once the project has been built. This means that if
you change an application object, you save it, and then close Visual Studio Code without building the project, the
rad.json won't update and then the project won't be considered "dirty".

For example, in a workspace with three projects; Leaf , Middle , and Base . Leaf depends on Middle and Base ,
and Middle depends on Base as illustrated below:

Assuming that:
All the three projects; Leaf , Base , and Middle have changed.
The Leaf project is the current project that is published.
Then all the three projects; Base , Middle , and Leaf will be part of the set that will be published.
In a scenario where Middle hasn't changed, but Leaf is still the startup project, then only Base and Leaf will be
published.
A new file is created to package the set dependencies called *.dep.app . This file gets transferred to the server
and it's deleted if publishing of the dependency set is successful.
Server publishing changes
Although server publishing is an internal step, it does have an impact on the dependency publishing and is
useful to know.
For example, in a workspace with two projects; Leaf depends on Base , and External and Indirect are projects
outside of the workspace as illustrated below:

Assuming that:
A workspace exists with Leaf and Base as workspace projects.
Base is published.
On the server Base , Leaf , External , and Indirect are already installed apps.
The following happens on the server:
All apps that depend on Base will be uninstalled, including External and Indirect dependency.
Any other apps that directly depend on Base and aren't published in the global scope - in this case Leaf and
External - are unpublished.
Base will be uninstalled, unpublished, and then published.
Leaf and External will be published, installed and then compiled against the newly published Base .
Important to notice here's that the External app also will be published.

Launch.json file setting


To control how dependency publishing is performed on the server, the launch.json file has a setting
dependencyPublishingOption with the following options:

SET T IN G DESC RIP T IO N

Default Set dependency publishing will be applied.

Ignore Dependency publishing is ignored. This setting should be


used cautiously, see note below.

Strict Dependency publishing will fail if there are any installed apps
that depend on the startup project.
NOTE
With the Ignore setting only Leaf will be published against what has already been published on the server for Middle
and Base . If a change has been done on Base that would break Leaf , even though local compilation would pass, the
server compilation will fail in this scenario. The benefit of using this option is to gain publishing time when Base is a large
project. Assuming that Base is published, then Leaf and Middle will be left untouched on the server. Only runtime errors
will reveal if Base has broken Middle and Leaf .

Global and workspace launch configuration


With Business Central version 21.1, you can add a launch property to a code-workspace or in the settings.json
file. For more information, see Global and workspace launch configuration.

Traverse the dependency graph


APPLIES TO: Business Central 2022 release wave 1 and later

To remove unnecessary manual work, use the AL: Publish full dependency tree for active project
command, which will traverse a project dependency graph in the workspace and install any required projects if
these aren't already deployed to the NST server. Find the command by using Ctrl+Shift+P or by using the
keyboard shortcut Shift+Alt+W . This will calculate the correct order in which to compile and publish the
dependencies of the current project and publish them using the launch.json option selected from the current
active project.

NOTE
Only project and app references covered by the workspace will be traversed. If the deployed AL project has dependencies
to apps that aren't included in the workspace, these will still have to be present or manually deployed in advance.

Incremental Build setting


If the al.incrementalBuild setting is set to true on workspaces with project to project references, all
resolutions will happen from the referenced project, instead of happening from an app in the \packagecache
folder, which will enhance the build time. For more information, see AL Language Extension Configuration.

Making sure that your project or workspace is updated


NOTE
When working in a project or workspace, some operations require that you run a Reload Window command (Ctrl+R)
for your project or workspace to ensure that it’s updated correctly. Examples are; source control operations like Git Pull,
changes made to the app.json file, or updating User or Workspace settings for AL.

See also
Development in AL
Best Practices for AL
Working with multiple AL project folders within one workspace
JSON Files
The Code Analysis Tool
2/6/2023 • 3 minutes to read • Edit Online

This article shows you how to use static code analysis tool on an AL project from within Visual Studio Code.

Enable the code analysis


Follow the steps below to create a basic project in AL.
1. Press Alt + A, Alt + L to create a new project.
2. Open the Command Palette Ctrl+Shift+P and choose either User Settings or Workspace Settings .
3. Under Extensions , go to Al Language extension configuration . When you scroll down, you'll find Code
Analyzers section, choose Edit in settings.json .
4. Set the al.enableCodeAnalysis in the settings file to true .
"al.enableCodeAnalysis": true
5. In the al.codeanalyzers setting, use Ctrl+Space to pick from the available code analyzers. Separate the list
of code analyzers with commas. For more information about the available analyzers, see AppSourceCop,
CodeCop, PerTenantExtensionCop, and UICop.
At this point, the selected analyzers will run on your project. Next, add some code to the project that will, in the
following example, be used to demonstrate a violation of the AA0001 "There must be exactly one space
character on each side of a binar y operator such as := + - AND OR =." code analysis rule.

NOTE
By default, code analysis is run in the background.

Add your own code to the project


In the Visual Studio Code Explorer, open the HelloWorld.al file and replace the existing code with the following
code:

pageextension 50100 CustomerListExt extends "Customer List"


{
trigger OnOpenPage();
var
result: Integer;
begin
// The following line will trigger the warning
// AA0001 "There must be exactly one space character on each side
// of a binary operator such as := + - AND OR =."
result := 2+2;
Message('2 + 2 = ' + Format(result));
end;
}

View the results of the code analysis


The code analysis tools will run in the background. You'll see the faulty expression underlined and the warning
"There must be exactly one space character on each side of '+'." will be displayed if you move cursor
over the underlined code. You can also view the list of issues by selecting the View tab of Visual Studio Code
and choosing the Problems option.
Using the Ctrl+Shift+B shortcut to build your project will run the code analysis tools on the entire project and
the detected issues will be displayed in the Output window of Visual Studio Code. For more information about
AL keyboard shortcuts, see Keyboard shortcuts.

Code analyzers
A code analyzer is a library that builds on the compiler's functionality to offer enhanced analysis of the syntax
and semantics of your code at build time. The AL Language extension for Visual Studio Code contains four
analyzers:
CodeCop is an analyzer that enforces the official AL Coding Guidelines. For more information about the
CodeCop rules, see CodeCop Analyzer Rules.
PerTenantExtensionCop is an analyzer that enforces rules that must be respected by extensions meant to
be installed for individual tenants. For more information about the PerTenantExtensionCop rules, see
PerTenantExtensionCop Analyzer Rules.
AppSourceCop is an analyzer that enforces rules that must be respected by extensions meant to be
published to Microsoft AppSource. For more information about the AppSourceCop rules, see AppSourceCop
Analyzer Rules.
UICop is an analyzer that enforces rules that must be respected by extensions that are meant to customize
the Web Client. For more information about the UserInterfaceCop rules, see UICop Analyzer Rules.

Enable code analysis on large projects


In order to improve performance while running code analysis on large projects, you can switch off running code
analysis in the background. To do so, open the Command Palette Ctrl+Shift+P and choose either User
Settings or Workspace Settings . Then, specify the setting "al.backgroundCodeAnalysis": false in settings file.

See Also
Using the Code Analysis Tools with the Ruleset
Ruleset for the Code Analysis Tool
Development in AL
Directives in AL
Debugging in AL
AL Language Extension Configuration
AL Compiler Diagnostics
2/6/2023 • 53 minutes to read • Edit Online

ID M ESSA GE DEFA ULT SEVERIT Y

AL0100 Unterminated multiline comment. Error

AL0101 Constant value '{0}' is outside the Error


range for a Decimal.

AL0102 Constant value '{0}' is outside the Error


range for a BigInteger.

AL0103 Constant value '{0}' is outside the Error


range for an Integer.

AL0104 Syntax error, '{0}' expected. Error

AL0105 Syntax error, identifier expected; '{1}' is Error


a keyword.

AL0106 Syntax error, 'TO' or 'DOWNTO' Error


expected.

AL0107 Syntax error, identifier expected. Error

AL0108 Indexers must have at least one value. Error

AL0109 Unexpected token. Error

AL0110 Orphaned ELSE statement. This is most Error


likely because of an unnecessary
semicolon placed just before the ELSE
keyword.

AL0111 Semicolon expected. Error

AL0112 {0} is not a valid attribute. Error

AL0113 At least one dimension must be Error


specified.

AL0114 Syntax error, integer literal expected. Error

AL0115 Object type expected. Error

AL0116 Invalid value for '{0}'. Allowed values Error


are '{1}'.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0117 Illegal statement. Only assignment and Error


method invocation can be used as a
statement.

AL0118 The name '{0}' does not exist in the Error


current context.

AL0119 The parameter name '{0}' is already Error


defined.

AL0120 A local or parameter named '{0}' Error


cannot be declared in this scope
because that name is used in an
enclosing local scope to define a local
or parameter.

AL0121 The variable name '{0}' is already Error


defined.

AL0122 Cannot implicitly convert type '{0}' to Error


'{1}'.

AL0123 The return value name '{0}' is already Error


defined.

AL0124 The property '{0}' cannot be used in Error


this context.

AL0125 Method name expected. Error

AL0126 No overload for method '{0}' takes {1} Error


arguments. Candidates: {2}.

AL0127 Member '{0}' cannot be used like a Error


method.

AL0128 Language identifier expected. Error

AL0129 The left-hand side of an assignment Error


must be a variable or field.

AL0130 A 'var' argument must be an Error


assignable variable.

AL0131 The property CharAllowed must be Error


specified in pairs of characters. The first
character in the pair must be equal to
or less than the second.

AL0132 '{0}' does not contain a definition for Error


'{1}'.

AL0133 Argument {0}: cannot convert from Error


'{1}' to '{2}'.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0134 '{0}' is not recognized as a valid type. Error

AL0135 There is no argument given that Error


corresponds to the required formal
parameter '{0}' of '{1}'.

AL0136 The loop variable in a 'for' statement Error


must be a numeric type.

AL0137 No enclosing loop out of which to Error


break.

AL0138 The case expression cannot be an Error


array.

AL0139 Since '{0}' doesn't have a return value, Error


EXIT cannot be called with a value.

AL0140 The expression is not valid for the Error


WITH statement.

AL0142 Only variables of type record can be Error


marked as TEMPORARY.

AL0143 Cannot apply indexing with [] to an Error


expression of type '{0}'.

AL0144 Wrong number of indices inside []; Error


expected {0}.

AL0145 Assignment is not valid for arrays. Error

AL0146 The maximum number of array Error


elements is {0}. Actual number is {1}.

AL0147 An array dimension must be a positive Error


number.

AL0148 The table filter is not valid. Error

AL0149 There is an 'ELSE' statement without Error


an 'IF' in property {0}.

AL0150 Invalid CONST expression. A valid Error


integer or an identifier is expected.

AL0151 Expression must be an Option. Error

AL0152 The value '{0}' is used more than once. Error

AL0153 The property '{0}' cannot be blank. Error


ID M ESSA GE DEFA ULT SEVERIT Y

AL0154 The maximum length for a field of type Error


'{0}' is {1}.

AL0155 A member of type {0} with name '{1}' is Error


already defined in {2} '{3}' by the
extension '{4}'.

AL0156 '{0}' is not a valid field type. Error

AL0157 '{0}' is not a valid variable type. Error

AL0158 '{0}' is not a valid parameter type. Error

AL0159 '{0}' is not a valid return type. Error

AL0160 '{0}' is not a valid language identifier. Error

AL0161 '{0}' is inaccessible due to its protection Error


level.

AL0162 '{0}' is not a valid trigger. Error

AL0163 Wrong signature. Correct signature for Error


'{0}' is '{1}'.

AL0164 The trigger '{0}' is already defined. Error

AL0165 Triggers cannot be called directly. Error

AL0166 Argument {0}: must be a member. Error

AL0167 The property '{0}' can only be set if the Error


property '{1}' is set with any of the
values of: '{2}'.

AL0168 The property '{0}' can only be set if the Error


property '{1}' is set.

AL0169 The option value '{0}' is not valid. Error

AL0170 An '=' is expected for property {0}. Error

AL0171 The property value '{0}' on property Error


'{1}' is not valid.

AL0172 Operator '{0}' is ambiguous on an Error


operand of type '{1}'.

AL0173 Operator '{0}' cannot be applied to an Error


operand of type '{1}'.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0174 Operator '{0}' is ambiguous on Error


operands of type '{1}' and '{2}'.

AL0175 Operator '{0}' cannot be applied to Error


operands of type '{1}' and '{2}'.

AL0176 Expected one of the calculation Error


formula methods
(Average,Count,Exist,Min,Max,Lookup,
Sum).

AL0177 Invalid application object identifier. A Error


number or an application object name
is expected.

AL0178 A 'FILTER' keyword or an identifier is Error


expected.

AL0179 An identifier or a member access Error


expression is expected.

AL0180 A 'FILTER' keyword is expected. Error

AL0181 Invalid filter expression. Error

AL0182 An identifier or a literal is expected as Error


the value of a filter expression.

AL0183 Unexpected character '{0}'. Error

AL0184 The expression '{0}' is not valid. Error

AL0185 {0} '{1}' is missing. Error

AL0186 Reference '{0}' in application object '{1}' Error


does not exist.

AL0187 Attribute '{0}' is valid only for {1}. Error

AL0189 Attribute '{0}' cannot be specified, Error


because '{1}' is already specified.

AL0190 Constant value '{0}' is outside the Error


range for a Time.

AL0191 Constant value '{0}' is outside the Error


range for a Date. The syntax for
defining Date format is yyyymmddD,
where D is a mandatory letter. For
example, 20180325D, read as the 25th
of March, 2018.

AL0192 The return value must be used for the Error


method '{0}'.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0193 Argument {0}: cannot convert from Error


'{1}' to the type of Argument 1 '{2}'.

AL0195 Invalid permission kind. Expected: '{0}'. Error

AL0196 The call is ambiguous between the Error


method '{0}' defined in {1} '{2}' by the
extension '{3}' and the method '{4}'
defined in {5} '{6}' by the extension
'{7}'.

AL0197 An application object of type '{0}' with Error


name '{1}' is already declared by the
extension '{2}'.

AL0198 Expected one of the application object Error


keywords ({0}).

AL0199 The type of the sum index field '{0}' Error


must be numeric (Decimal, BigInteger,
Integer, or Duration).

AL0200 Property '{0}' is obsolete and will be Warning


removed in a future version.

AL0201 The {0} FlowField is not a Boolean field. Error


If a FlowField CalcFormula starts with
'Exist', then the FlowField must be a
Boolean type field.

AL0202 The {0} FlowField is not an Integer field. Error


If a FlowField CalcFormula starts with
'Count', then the FlowField must be an
Integer type field.

AL0203 Cannot calculate Sum or Average for Error


the field {0} because it is not a numeric
field (Decimal, BigInteger, Integer, or
Duration data type).

AL0204 Field type {0} is not convertible to field Error


type {1}.

AL0206 A field with ID {0} is already defined in Error


{1} '{2}' by the extension '{3}'.

AL0207 The expression must be of Text type. Error

AL0208 The expression must be of Boolean Error


type.

AL0210 A control with ID = {0} is already Error


defined.

AL0211 Unknown area type '{0}'. Error


ID M ESSA GE DEFA ULT SEVERIT Y

AL0212 An area of type '{0}' is already defined. Error

AL0213 An area of type '{0}' is only valid on Error


pages of type '{1}'.

AL0214 An area of type 'FactBoxes' is not valid Error


on Part type pages.

AL0215 A Part type page cannot contain other Error


parts.

AL0216 Only parts are valid in an area of type Error


'FactBoxes'.

AL0217 Only parts and groups are valid in an Error


area of type 'RoleCenter'.

AL0218 An integer literal value is expected for Error


property {0}.

AL0219 Syntax error, string literal expected. Error

AL0220 Syntax error, boolean literal expected. Error

AL0221 The value '{0}' is not valid. The valid Error


range is {1}..{2}.

AL0222 The ID '{0}' is not valid. ID's must be Error


greater than zero.

AL0223 The property '{0}' can only be set if the Error


property '{1}' is set to '{2}'.

AL0224 Expression expected. Error

AL0227 A key with ID {0} is already defined. Error

AL0228 A field group with ID {0} is already Error


defined.

AL0229 The data type on the {0} field is not Error


valid because the ExtendedDatatype
property is set to Ratio. Valid data
types are Integer, BigInteger and
Decimal.

AL0230 The data type on the {0} field is not Error


valid because the ExtendedDatatype
property is set to PhoneNo, URL or
Email. Valid data types are Code and
Text.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0231 A member with ID '{0}' is already Error


defined in {1} '{2}' by the extension
'{3}'.

AL0232 The property value on field '{0}' must Error


be positive or zero.

AL0234 An action with ID = {0} is already Error


defined.

AL0235 The expression CONST() on the option Warning


value '{0}' is obsolete. Use CONST(" ")
to refer to the empty option value.

AL0236 An empty CONST() expression is not Error


allowed on field '{0}' of type '{1}'.

AL0238 No overload for attribute '{0}' expects Error


{1} arguments.

AL0239 Attribute {0} is specified multiple times. Error

AL0240 The signature of procedure '{0}' does Error


not match the signature required by
attribute '{1}': parameter {2} is
expected to be of type '{3}' but found
type '{4}'. The expected signature is:
{5}.

AL0241 The signature of procedure '{0}' does Error


not match the signature required by
attribute '{1}'. The expected signature
is: {2}.

AL0242 Invalid attribute argument syntax: '{0}'. Error

AL0243 Attribute {0} can only be used within a Error


codeunit of subtype {1}.

AL0244 The signature of procedure '{0}' does Error


not match the signature required by
attribute '{1}': return value is expected
to be of type '{2}' but found type '{3}'.
The expected signature is: {4}.

AL0245 The signature of procedure '{0}' does Error


not match the signature required by
attribute '{1}': procedure cannot be
local.

AL0246 The property '{0}' cannot be Error


customized.

AL0247 The target {0} {1} for the extension Error


object is not found.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0249 The Page '{0}' is not found. Error

AL0250 The data type on the {0} field is not Error


valid because the ExtendedDatatype
property is set to Person. Valid data
types are Media and MediaSet.

AL0251 Application object '{0}' is missing. Warning

AL0252 Expected 'Ascending' or 'Descending' Error


value.

AL0254 Sorting field '{0}' should be part of the Warning


keys for table '{1}'.

AL0255 Property '{0}' requires an application Error


object reference for the 'RunObject'
property.

AL0256 The flowfield '{0}' cannot be part of the Error


keys for table '{1}'.

AL0257 Constant value '{0}' is outside the Error


range for a DateTime data type, only 0
is valid.

AL0259 A SQLIndex defined for the primary Error


key must contain the same fields as
the key for table '{0}'.

AL0260 The key '{0}' on table '{1}' cannot start Error


with the fields defined for the primary
key. The server will append these to
any alternate key.

AL0261 The identifier '{0}' can only be specified Error


in the list once.

AL0262 The clustered key '{0}' has already been Error


defined for table '{1}'.

AL0263 The primary key '{0}' on table '{1}' (the Error


first one in the key list) must be
enabled.

AL0264 An application object of type '{0}' with Error


ID '{1}' is already declared by the
extension '{2}'.

AL0266 Pages of types 'CardPart' and 'ListPart' Error


can only contain Processing areas.

AL0267 Actions are not allowed on the control Error


type.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0268 Grouping of actions is not allowed. Error

AL0269 The referenced page '{0}' should be a Warning (Future Error)


list part or a card part.

AL0270 The control '{0}' is not found in the Error


target '{1}'.

AL0271 The action '{0}' is not found in the Error


target '{1}'.

AL0272 The anchoring symbol '{0}' must be a Error


grouping symbol.

AL0273 The name '{0}' is an Area type. Using Warning (Future Error)
an Area type name will limit
extensibility as dependent extension
won't be able to reference it.

AL0274 The anchoring symbol '{0}' cannot be Error


an area.

AL0275 '{0}' is an ambiguous reference Error


between '{1}' defined by the extension
'{2}' and '{3}' defined by the extension
'{4}'.

AL0276 A Time literal value is expected for Error


property {0}.

AL0277 A Date literal value is expected for Error


property {0}.

AL0278 A DateTime literal value is expected for Error


property {0}.

AL0279 The key '{0}' on table '{1}' contains too Error


many fields.

AL0280 The event '{0}' is not found in the Error


target.

AL0281 Object member '{0}' is not an event. Error

AL0282 The member referenced by event Error


subscriber '{0}' parameter '{1}' is not
found.

AL0283 The event '{0}' must not have a return Error


value.

AL0284 The type of the parameter '{1}' on the Error


event subscriber '{0}' does not match
the expected type '{2}'.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0285 The event '{0}' must not have a Error


parameter name 'sender' when it
specifies to include sender.

AL0286 The event '{0}' can't contain code. Error

AL0287 The event '{0}' can't contain local Error


variables.

AL0288 Parameter '{0}' is only allowed to be Error


'var' if the publisher parameter is 'var'.

AL0290 Element name is not allowed for the Error


event '{0}' and must be empty.

AL0291 Event trigger '{0}' can only be used if Error


the page specifies the 'SourceTable'
property.

AL0292 'FIELD', 'CONST' or 'FILTER' keyword is Error


expected.

AL0293 Property value {0} is not in the field's Error


OptionMembers.

AL0294 The type of property value {0} does Error


not match the field’s type.

AL0295 The field '{0}' is not found in the target Error


'{1}'.

AL0296 The application object or method '{0}' Error


has scope '{1}' and cannot be used for
'{2}' development.

AL0297 The application object identifier '{0}' is Error


not valid. It must be within the allowed
ranges '{1}'.

AL0298 The data type of the expression Error


assigned to the 'StyleExpr' property is
not valid. Valid data types are Boolean,
Text, or Code.

AL0299 Member name '{0}' is only allowed on Warning (Future Error)


triggers.

AL0300 The property '{0}' is used as a method. Error

AL0301 A list must end with a member; not a Error


separator {0}.

AL0302 Cannot use '{0}' in {1} '{2}' before it is Error


declared.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0303 Attributes can only be defined on Error


variables and methods.

AL0304 Length of the identifier '{0}' cannot Error


exceed {1} characters.

AL0305 The length of the application object Error


identifier '{0}' cannot exceed {1}
characters.

AL0306 A field list has to contain at least one Error


field.

AL0307 Property value cannot be validated Error


because the source table is
unreachable.

AL0308 The primary key '{0}' on table '{1}' (the Error


first one in the key list) must have the
MaintainSqlIndex property set to true.

AL0309 Table '{0}' contains too many keys. Error

AL0310 An instance is required for the non- Error


static member '{0}'.

AL0311 Member '{0}' cannot be accessed with Error


an instance reference; qualify it with
'{1}' instead.

AL0313 Attribute {0} can only be used within Error


{1}.

AL0314 The property '{0}' is only valid in Error


controls of type '{1}'.

AL0315 Control '{0}' does not exist in group Error


'{1}'.

AL0316 The expression must be of Integer Error


type.

AL0317 A property with the same name has Error


already been declared.

AL0318 The value assigned to the 'RunObject' Error


property is not valid. Valid object types
are codeunit, page, xmlport, report,
and query.

AL0319 At least one target has to be specified Error


for the move.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0320 The referenced page '{0}' must specify Error


a 'SourceTable'.

AL0321 Variable {0} cannot be included in the Error


data set.

AL0322 {0} is not valid for client expressions. Error

AL0323 The value assigned to the SystemPart Error


type is not valid. Valid values are {0}.

AL0324 The language {0} must only be Error


specified one time.

AL0325 The field '{0}' in the table '{1}' cannot Error


be included in a key because its type is
'{2}'.

AL0326 '{0}' is not a valid column type. Error

AL0327 Missing file '{0}'. Error

AL0329 The {0} property must reference a top- Error


level DataItem.

AL0331 The property 'DataItemLink' cannot be Error


set on a top-level DataItem.

AL0332 The control {0} must be of type {1}. Error

AL0333 The syntax for accessing fields is not Error


valid. Specify target field with
'tableName.fieldName' syntax.

AL0334 The extension object '{0}' cannot be Error


declared. Another extension for target
'{1}' or the target itself is already
declared in this module.

AL0335 Attributes must be specified before Error


elements inside of an element.

AL0336 There must be exactly one root node Error


and it has to be an element.

AL0337 None of the specified parent table Error


elements has the name {0}.

AL0338 Event trigger '{0}' can only be used if Error


the page specifies 'SourceTable'. Table
'{1}' is missing.

AL0340 Page '{0}' should be of type Error


'RoleCenter'.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0341 '{0}' property is missing. Error

AL0342 You cannot combine two DataItems at Error


the same level because unions are not
supported.

AL0343 Queries must define a top-level Error


DataItem.

AL0344 The property 'DataItemLink' must be Error


set.

AL0345 The source of a Column or Filter must Error


be a field defined on the table
referenced by its parent DataItem.

AL0346 The methods '{0}' can only be used on Error


Columns that have a Date or DateTime
type.

AL0347 The methods '{0}' can only be used on Error


Columns that have a Decimal,
BigInteger, Integer, or Duration type.

AL0349 Column '{0}' does not exist in Error


application object '{1}'.

AL0350 The column '{0}' cannot be used Error


multiple times when defining the order
of the resulting dataset.

AL0351 The property 'DataItemLink' can only Error


reference fields on ancestor data items.

AL0352 Queries must define at least one Error


Column.

AL0353 A Column must have a valid data Error


source or have the 'Method' property
set to 'Count'.

AL0354 Cannot move element '{0}' relative to Error


itself in page '{1}'.

AL0355 Cannot move the {0} '{1}' multiple Error


times inside of a single move
operation.

AL0356 Cannot modify the {0} '{1}' multiple Error


times.

AL0357 Cannot add {0} '{1}' with the same Error


name multiple times.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0358 Cannot move or modify the {0} '{1}' in Error


the same '{2}' that you added.

AL0359 The XML node name is not valid. {0}. Error

AL0360 Text literal was not properly Error


terminated. Use the character ' to
terminate the literal.

AL0361 Identifier was not properly terminated. Error


Use the character " to terminate the
identifier.

AL0362 The path must be relative to the Error


project root.

AL0363 The directory separator used in this Error


property value is not compatible with
the current operating system.

AL0364 Option members must be accessed Error


with ::.

AL0365 The property '{0}' cannot be set if the Error


property '{1}' is set to '{2}'.

AL0366 A table has to have at least one Error


Normal field.

AL0367 An array must have at least one Error


dimension.

AL0368 The maximum number of array Error


dimensions is {0}.

AL0369 Constant value '{0}' cannot be Error


converted to a '{1}'.

AL0370 Division by constant zero. Error

AL0371 The operation overflows at compile Error


time.

AL0372 The length of the String constant Error


exceeds the current memory limit.

AL0373 The XML name cannot be empty. Error

AL0374 The use of a unique ID has been Warning


deprecated and the ID can be
removed.

AL0375 Option members cannot contain Error


comma.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0376 A control of type '{0}' is not allowed in Error


a parent control of type '{1}'.

AL0377 '{0}' is not a valid value for the '{1}' Error


attribute on variables of type '{2}'.

AL0378 A page of type Role Center cannot Error


have triggers.

AL0379 The name '{0}' cannot be used as an Error


identifier because it does not comply
with the Common Language
Specification.

AL0380 Cannot move symbol '{0}' from '{1}' Error


area to '{2}' area.

AL0381 The keys '{0}' and '{1}' have an identical Error


list of fields.

AL0382 The option value '{0}' is defined more Error


than once on field '{1}'.

AL0383 The option value '{0}' is not defined on Error


field '{1}'.

AL0384 The name of all the columns and all Error


the labels defined in a report must be
unique.

AL0385 IncludeCaption can be set to true only Error


if the source of the column is a named
field.

AL0386 A required package dependency could Error


not be found. Make sure that you
have downloaded all the referenced
packages and their dependencies.

AL0387 Namespace '{0}' is already specified. Error

AL0388 The date formula '{0}' must include Error


plus (+) or minus (-).

AL0389 The date formula '{0}' contains a Error


number that is too large. The number
must be in the range {1} - {2}.

AL0390 The date formula '{0}' must include a Error


time unit. Time units can be:
D,WD,W,M,Q, or Y. C specifies the
current time unit based on date and
can be used as a prefix to any of the
time units.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0391 The date formula '{0}' must include a Error


number.

AL0392 The input cannot be longer than {0}. Error

AL0393 Application object {0} is already Error


referenced.

AL0395 You can only specify Move and Modify Error


actions in the layout section of a page
customization.

AL0396 Procedures and triggers are not Error


allowed on page customizations.

AL0397 The name '{0}' clashes with '{1}' Error


column's format column name.

AL0398 Constant value '{0}' is outside of the Error


valid ordinal range for this {1} type.

AL0399 Global variables are not allowed on Error


page customizations.

AL0401 Multiple page customizations have Error


been specified for the same page {0}
within the same profile.

AL0402 Expression {0} cannot be specified Error


more than once in a 'case' statement.

AL0403 To modify '{0}' you must add at least Error


one property or trigger.

AL0404 Property '{0}' is not allowed on a table Error


extension.

AL0405 An option value is expected. Error

AL0406 The type for {0} is not valid. Expected Error


{1}, but found {2}.

AL0407 The generic '{0}' type expects {1} type Error


arguments.

AL0408 The type '{0}' cannot be used as a type Error


argument in this context.

AL0409 The '{0}' type is not a generic type. Error

AL0410 The report '{0}' doesn't contain a Error


Request Page.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0411 {0} can be specified only once. Error

AL0412 Member '{0}' could not be declared in Error


an object of type '{1}'.

AL0413 Procedure '{0}' cannot have a body. Error

AL0414 Procedure '{0}' must declare a body. Error

AL0415 Keyword 'local' cannot be specified for Error


procedure '{0}'.

AL0416 Method '{0}' cannot have a return Error


value.

AL0417 Control add-in '{0}' not found. Error

AL0418 The format of resource '{0}' is not valid. Error


Resources in the control add-in should
either be relative to the project root, or
reference external files using the HTTP
or HTTPS protocol.

AL0419 The event subscriber '{0}' is missing a Error


parameter of type '{1}'.

AL0420 Parameter '{0}' cannot be 'var'. Error

AL0421 A ‘foreach’ statement can only be used Error


with an expression of an enumerable
type.

AL0422 Constant value {0} is not a valid value Error


for APIVersion. Valid values are 'beta'
or of type 'vX.Y' where X and Y
represent positive integers.

AL0423 The property '{0}' can only be set if the Error


specified fields are from the same
table.

AL0424 The multilanguage syntax is being Warning


deprecated. Please update to the new
syntax.

AL0425 The '{0}' trigger can only be used on Error


codeunits that have the Subtype
property set to '{1}'.

AL0426 The APIVersion {0} is specified multiple Error


times.

AL0427 Field {0} cannot be converted to type Error


{1}.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0428 Cannot specify {0} and {1} property at Error


the same time. Use only the {1}
property.

AL0429 A repeater control can only be added Error


to pages that have a source table.

AL0430 The parameter '{0}' has a type which is Error


not serializable and therefore cannot
be used in the given context.

AL0432 {0} '{1}' is marked for removal. {2}. Warning

AL0433 {0} '{1}' is removed. {2}. Error

AL0434 Syntax error, numeric literal expected. Error

AL0435 Syntax error, literal expected. Error

AL0436 The value of the property '{0}' cannot Error


be empty.

AL0437 The value of the '{0}' property cannot Error


include empty members.

AL0438 The type of value {0} does not match Error


the field’s type.

AL0439 The label's property is not valid. Error


Possible properties are: {0}.

AL0440 The '{0}' already defines a method Error


called '{1}' with the same parameter
types in '{2}'.

AL0441 Parameter {0} is only available when Error


the page specifies a 'SourceTable'.

AL0442 Parameter {0} is only available when Error


the page specifies a 'SourceTable'. Table
'{1}' is missing.

AL0443 The system object provided is not one Error


of the valid system objects.

AL0444 Malformed {0} report layout at Error


location '{1}'. The issue is: '{2}'.

AL0445 The file '{0}' is opened in another Error


application. Close the application to be
able to compile.

AL0447 The value '{0}' for the property '{1}' Error


cannot be used for '{2}' development.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0448 Member is not allowed in this context. Error

AL0449 The alias '{0}' is already declared. Error

AL0450 Field '{0}' is removed and cannot be Error


used in an active key.

AL0451 An assembly named '{0}' could not be Error


found in the assembly probing paths
'{1}'.

AL0452 The type '{0}' could not be found in Error


assembly '{1}'.

AL0453 This feature is under development. It Error


can be enabled by using the '{0}'
feature flag.

AL0454 The {0} {1} of type {2} cannot be Error


extended.

AL0455 Option ordinal value '{0}' is not valid. Error


Valid values are -1 and positive
integers.

AL0456 The number of option ordinal values is Error


not valid. There must be as many
option ordinal values as there are
option members.

AL0457 The label syntax is not correct. Please Warning


move the '{0}' to its designated
attribute.

AL0458 '{0}' is not a valid attribute on variables Error


of type '{1}'.

AL0459 The attribute '{0}' is only allowed on Error


global variables.

AL0460 Client-side events are supported only Error


on pages and page extensions.

AL0461 '{0}' is not a valid event publisher. Error

AL0462 The publisher '{0}' does not have any Error


public events named '{1}'.

AL0463 Parameter '{0}' must be 'var' if and only Error


if the publisher parameter is 'var'.

AL0464 Could not determine a suitable default Error


primary key for table '{0}'. Please
specify a primary key for the table.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0465 The property '{0}' does not accept Error


references to external files.

AL0466 Cannot access file '{0}'. The file is most Error


likely read-only.

AL0467 Cannot access file '{0}'. The file is most Warning


likely read-only.

AL0468 Length of the table field name '{0}' Warning (Future Error)
must not exceed {1} characters. Longer
field names are prone to cause SQL
errors.

AL0470 The referenced page '{0}' of PageType Error


'HeadlinePart' is only allowed inside
pages of PageType 'RoleCenter'.

AL0471 The format of link '{0}' is not valid. It Error


should be using the HTTP or HTTPS
protocol.

AL0472 The source of the translation item does Warning


not match the label value. Ignoring the
translation item.

AL0473 The translated string of the translation Warning


item is too long. Trimming the
translated string.

AL0474 The attribute '{0}' is only allowed on Error


local variables.

AL0475 The attribute '{0}' cannot be used on Error


variables of array type.

AL0476 The trigger '{0}' can only be used if the Error


property '{1}' of '{2}' is set.

AL0477 The trigger '{0}' can only be used if the Error


property '{1}' of '{2}' is set to '{3}'.

AL0478 The trigger '{0}' can only be used if the Error


property '{1}' of '{2}' is set with any of
the values of :'{3}'.

AL0479 There must be only one translation Warning


item for each ID.

AL0480 Attributes cannot have nested Error


elements.

AL0481 The property Image can only be used Warning (Future Error)
on fields that are contained in a
CueGroup control.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0482 The image {0} is not valid in this Warning


context.

AL0483 The property Image cannot be used Warning


on nested Action Groups inside the
'Sections' area.

AL0484 The property '{0}' must be Error


alphanumeric.

AL0485 The property '{0}' is mandatory for Error


objects of type API.

AL0486 A member of type {0} with name '{1}' is Warning (Future Error)
already defined in {2} '{3}' by the
extension '{4}'.

AL0487 The field '{0}' is not of field class Error


'Normal' and thus cannot be part of
the {1} list.

AL0488 ControlAddIn name must not contain Error


characters {0}.

AL0489 The property expression is not valid. A Error


CONST or FILTER expression is
expected.

AL0490 The property expression is not valid. A Error


CONST, FIELD, or FILTER expression is
expected.

AL0491 The property expression is not valid. Error


One of the following expressions is
expected :
CONST,FIELD,FILTER,FIELD(FILTER(Ident
ifier)),FIELD(UPPERLIMIT(Identifier)),or
FIELD(UPPERLIMIT(FILTER(Identifier))).

AL0492 The RunObject property value of Error


actions defined in the '{0}' area must
only reference pages of type 'List'.

AL0493 The RunObject property value of Warning (Future Error)


actions defined in the '{0}' area must
only reference pages of type 'List'.

AL0494 The action area '{0}' can only directly Error


contain groups.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0495 A member with ID '{0}' is already Error


defined. Change the member name to
generate a new ID.

AL0496 Attributes cannot be defined in this Error


context.

AL0498 The attribute '{0}' can only be used on Error


procedures that have the attribute
'{1}'.

AL0499 The handler function {0} was not Error


found. Make sure the procedure is
defined and has a handler attribute.

AL0500 The HandlerFunctions attribute only Error


accepts a string representing a comma
separated list of procedure names
without spaces.

AL0501 Eventsubscribers in test codeunits Error


must use manual binding. Set the
property EventSubscriberInstance to
Manual.

AL0502 The LinkTable property must reference Error


a table element node of the current
XMLPort.

AL0503 Reference '{0}' in application object '{1}' Error


is ambiguous.

AL0504 The enum '{0}' is not extensible. Error

AL0505 Pages of type API must have the Error


'DelayedInsert' property set to true.
From runtime 7.2, 'DelayedInsert' can
be set to false if the 'Editable' property
or the 'InsertAllowed' property is set
to false.

AL0509 Constant value '{0}' is outside of the Warning


valid ordinal range for this option type.

AL0510 The .NET type '{0}' is not a valid control Error


add-in.

AL0511 The property 'IsControlAddIn' must be Error


set on the .NET type '{0}' if the type
represents a .NET control add-in.

AL0512 The manifest should define the Error


'supportedLocales' manifest property
in order to use a placeholder in the
'{0}' property.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0513 The FieldGroup '{0}' is not found in the Error


target '{1}'.

AL0514 The symbol file is not valid. An enum Error


with ID '{0}' is already defined with a
different name in module '{1}'.

AL0515 The symbol file is not valid. An enum Error


with name '{0}' is already defined with
a different ID in module '{1}'.

AL0516 The symbol file is not valid. An enum Error


with ID '{0}' and name '{1}' is already
defined in module '{2}', but with
different values (OptionString).

AL0517 The link '{0}' specified in the HelpLink Error


property must either contain one
placeholder with value 0 for the user
locale, or no placeholders.

AL0518 A method with name '{0}' possessing Error


one Handler attribute is already
defined in this test codeunit.

AL0519 '{0}' is not valid value in this context. Error

AL0520 {0} '{1}' is removed. {2}. Warning

AL0521 The primary key '{0}' on table '{1}' (the Error


first one in the key list) must not have
the Unique property set.

AL0522 Property value {0} is not in the values Error


for enum '{1}'.

AL0523 The '{0}' already defines a method Warning (Future Error)


called '{1}' with the same parameter
types in '{2}'.

AL0524 The base type already defines a Warning (Future Error)


method called '{0}' with the same
parameter types.

AL0525 The system or virtual table '{0}' cannot Error


be extended.

AL0526 The referenced page '{0}' of type 'API' Error


is only allowed inside pages of
PageType 'API'.

AL0527 The SQL timestamp field '{0}' cannot Error


be part of the keys for table '{1}'.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0528 The name of field controls in pages of Error


the type API must be alphanumeric.

AL0529 The name of columns in queries of the Error


type API must be alphanumeric.

AL0530 The maximum length for the type '{0}' Error


is {1}.

AL0531 The page '{1}' of type 'API' and its Error


subpage '{2}' of type 'API' in the
control '{0}' of type 'Part' must have
the same value of property '{3}'.

AL0532 The page '{1}' of type 'API' and its Error


control '{0}' of type 'Part' must have
the same value of property '{2}'.

AL0533 The view '{0}' is not found in the target Error


'{1}'.

AL0534 Length of the table key name '{0}' Warning (Future Error)
must not exceed {1} characters. Longer
key names are prone to cause SQL
errors.

AL0535 The referenced page '{0}' must be a Error


List part, a Card part, or an API page.

AL0536 Adding new controls in a view is not Error


allowed.

AL0537 Declaring views is only supported on Error


pages of type {0}.

AL0538 Views only support setting one sorting Error


direction on table fields.

AL0539 The field '{0}' cannot be used multiple Error


times when defining the order of the
page view.

AL0540 The view name '{0}' is not valid. Error

AL0541 The use of the variable '{0}' in the Error


property value of '{1}' in view '{2}' is
not allowed.

AL0542 The property {0} cannot be used on Error


page '{1}' because this page does not
have a source table.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0543 The manifest property Error


'contextSensitiveHelpUrl' must be set
in order to use the property
'ContextSensitiveHelpPage'.

AL0544 The property Error


'ContextSensitiveHelpPage' cannot
contain a placeholder.

AL0545 An area of type '{0}' is not valid on Warning (Future Error)


pages of type '{1}'.

AL0546 The control '{0}' cannot be modified in Error


a view context because views only
support modifying controls defined in
the Content area.

AL0547 The event '{0}' should not expose Warning (Future Error)
global variables.

AL0548 Cannot move symbol '{0}' from '{1}' Warning (Future Error)
area to '{2}' area.

AL0549 Procedures and triggers are not Error


allowed on page views.

AL0550 Groups defined in the action area '{0}' Warning (Future Error)
should only contain actions.

AL0551 The action area '{0}' can only contain Warning (Future Error)
actions.

AL0552 The action area '{0}' can only directly Warning (Future Error)
contain groups.

AL0553 You cannot add actions of type '{0}' in Error


the action area '{1}' from a page
customization. You can only add
actions of type '{2}'.

AL0554 You can only specify Move and Modify Error


actions in the actions section of a page
customization.

AL0555 The RunObject property value of Error


actions defined in the '{0}' area must
only reference objects of type {1}.

AL0556 The RunObject property value of Warning (Future Error)


actions defined in the '{0}' area must
only reference objects of type {1}.

AL0557 The name of the codeunit local variable Warning


'{0}' is identical to a field in table '{1}'
and will shadow that table field.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0558 The name of the codeunit global Warning


variable '{0}' is identical to a field in
table '{1}'.

AL0559 A Part type page cannot contain other Warning (Future Error)
parts.

AL0560 Only parts and groups are valid in an Warning (Future Error)
area of type 'RoleCenter'.

AL0561 Only parts are valid in an area of type Warning (Future Error)
'FactBoxes'.

AL0562 The value assigned to the SystemPart Warning (Future Error)


type is not valid. Valid values are {0}.

AL0563 A control of type '{0}' is not allowed in Warning (Future Error)


a parent control of type '{1}'.

AL0564 The object {0} '{1}' is not extensible. Error

AL0565 Fast publishing requires a built Error


application file to be present. The '{0}'
application file contains a manifest
which is not valid. Please rebuild the
application file before continuing with
fast publishing.

AL0566 The field '{0}' is using an Id {1} that is Error


reserved for system fields.

AL0567 The field '{0}' is using the same name Warning


as a system-provided field and will
shadow that field.

AL0568 Groups defined in the action area '{0}' Warning (Future Error)
should only contain actions or groups.

AL0569 A page of type Role Center cannot Warning (Future Error)


have procedures.

AL0570 The symbol '{0}' results in the same Error


translation ID as one or more other
symbols. Rename symbol to resolve
the problem.

AL0571 The property 'Description' should only Warning (Future Error)


be used for internal comments. Use
the property 'Caption' or 'CaptionML'
in order to specify the profile caption
displayed to end users.

AL0572 I/O operations on the file or folder '{0}' Error


resulted in an exception with the
Windows 32 error code '{1}'.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0573 {0} is not valid for client expressions. Warning (Future Error)

AL0574 This feature is under development and Error


cannot be used in an extension.

AL0575 You cannot modify the {0} '{1}' because Error


it is defined in the page customization
'{2}'.

AL0576 The profile name '{0}' is not valid Error


because it contains leading or trailing
spaces.

AL0577 The view '{0}' cannot define layout Error


changes because its property '{1}' is
not set to false.

AL0578 The value for the property '{0}' is not Error


valid because its length exceeds {1}
characters ({2} characters).

AL0579 The value for the property '{0}' for the Error
language code '{1}' is not valid because
its length exceeds {2} characters ({3}
characters).

AL0580 The field '{0}' is used by the system Error


and cannot be specified as a table key.

AL0581 The length for the type '{0}' must be Error


positive.

AL0582 '{0}' does not implement the interface Error


member '{1}'.

AL0584 An interface member cannot have any Error


variables.

AL0585 An interface cannot have any variables. Error

AL0586 The identifier contains characters that Warning (Future Error)


are not valid: {0}.

AL0587 '{0}' is already listed in the interface list. Error

AL0588 The type of parameter '{1}' on event Warning


subscriber '{0}' is of type 'Option', but
the expected type is '{2}'. Please
update the subscriber type to match
the publisher.

AL0589 The name '{0}' is used across multiple Warning (Future Error)
columns and data items. This will
prevent extensibility of this column or
data item.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0590 The property {0} is only supported on Warning (Future Error)


{1}.

AL0591 The property {0} is only supported on Error


{1}.

AL0592 Compatibility: {0}. Warning

AL0593 The type of the parameter '{0}' on the Warning (Future Error)
event subscriber '{1}' has a smaller
capacity than the parameter type '{2}'
on the publisher.

AL0594 An error occurred during XML Error


serialization of metadata for symbol:
'{0}'. Error: {1}.

AL0595 '{0}' does not implement {1}. Error

AL0596 Value '{0}' does not implement Error


interface '{1}' and there is no default
implementation for the mentioned
interface.

AL0598 Cannot move or modify the {0} '{1}' in Warning (Future Error)
the same '{2}' that you added.

AL0599 A control add-in with the same Error


internal name '{0}' is already defined.

AL0600 The property '{0}' can only be set on Warning (Future Error)
elements of type Option.

AL0601 {0} '{1}' is removed. {2}. Warning (Future Error)

AL0602 '{0}' is inaccessible due to its protection Warning (Future Error)


level.

AL0603 An implicit conversion is being Warning (Future Error)


performed from a value of type '{0}' to
a value of type '{1}'. This conversion
can lead to unexpected runtime issues.

AL0604 Use of implicit 'with' will be removed in Warning (Future Error)


the future. Qualify with '{0}'.

AL0605 Use of implicit 'with' will be removed in Hidden


the future. Qualify with '{0}'.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0606 The 'with' statement is deprecated and Warning (Future Error)


will be removed for cloud development
in a future release.

AL0607 The 'with' statement is deprecated and Hidden


will be removed for cloud development
in a future release.

AL0608 The OrderBy property must specify at Warning (Future Error)


least one field on which to sort the
data.

AL0609 Adding actions to CueGroups is not Warning


supported.

AL0610 Moving actions in CueGroups is not Warning


supported.

AL0611 Modifying actions in CueGroups is not Warning


supported.

AL0612 An interface member must be a Error


'procedure'.

AL0613 Wrong signature. Correct signature for Warning (Future Error)


'{0}' is '{1}'.

AL0614 The value '{0}' is not allowed for Warning (Future Error)
property '{1}'.

AL0615 Field '{0}' is not specified as a source Warning (Future Error)


expression on page '{1}'. All fields
specified in ODataKeyFields must be
used as the source expression in a
page control.

AL0616 Defining the contract '{0}' on interface Error


'{1}' is not allowed because it is
matching a built-in procedure for
codeunits.

AL0617 Event trigger 'OnBeforeActionEvent' Warning (Future Error)


cannot be used because the action '{0}'
specifies the 'RunObject' property.

AL0619 The attribute '{0}' on procedure '{1}' is Error


not allowed. Add attribute
'ServiceEnabled' to the procedure or
move it into an application object of
type API.

AL0620 Preprocessor directives must appear as Error


the first non-whitespace character on a
line.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0621 Preprocessor directive expected. Error

AL0622 #endregion directive expected. Error

AL0623 #endif directive expected. Error

AL0624 Unexpected preprocessor directive. Error

AL0625 Cannot define/undefine preprocessor Error


symbols after first token in file.

AL0626 Expected identifier or numeric literal. Warning

AL0627 Expected 'disable' or 'restore' keyword. Warning

AL0628 Unrecognized #pragma directive. Warning

AL0629 Preprocessor expression is not valid. Error

AL0630 Unrecognized escape sequence. Error

AL0631 Single-line comment or end-of-line Error


expected.

AL0632 Closing parenthesis ')' expected. Error

AL0633 Expected 'disable', 'enable' or 'restore' Warning


keyword.

AL0634 Single-line comment or end-of-line Warning


expected.

AL0635 A method with 'OnPrem' scope cannot Warning (Future Error)


be used as event subscriber. It will fail
at runtime when the publisher has
'Cloud' scope.

AL0636 The data type on the field '{0}' is not Error


valid because the ExtendedDatatype
property is set to RichText. Valid data
types are Text, BigText and Blob.

AL0637 The property 'NavigationPageId' must Error


be defined on a page of pagetype
'API'.

AL0638 'Variant' is not a valid column type for Error


column '{0}' in report '{1}'.

AL0639 'Variant' is not a valid column type for Warning (Future Error)
column '{0}' in report '{1}'.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0640 XML comment has badly formed XML Warning


-- '{0}'.

AL0641 Parameter '{0}' has no matching param Warning


tag in the XML comment for '{1}' (but
other parameters do).

AL0642 Missing XML comment for publicly Warning


visible type or member '{0}'.

AL0643 XML comment is not placed on a valid Warning


language element.

AL0644 XML comment has a param tag for Warning


'{0}', but there is no parameter by that
name.

AL0645 XML comment on '{1}' has a paramref Warning


tag for '{0}', but there is no parameter
by that name.

AL0646 XML comment has a duplicate param Warning


tag for '{0}'.

AL0647 {0}. See also error AL{1}. Warning

AL0648 End-of-file found, '*/' expected. Error

AL0649 Comma is not supported in enum Warning (Future Error)


value names or in captions. Enum
Value = '{0}', Property = '{1}'.

AL0650 The text with a length of {0} is longer Warning (Future Error)
than the MaxLength of {1} which
means that the text will be trimmed.

AL0651 '{0}' cannot be contained since it Error


causes a circular reference.

AL0652 The permission set '{0}' cannot contain Error


itself.

AL0653 Ids are not supported as object Error


reference.

AL0654 The property value contains an Error


unexpected file extension: {0}. The
expected extensions are {1}.

AL0655 The property DataItemLinkReference Warning (Future Error)


can only refer to an ancestor DataItem.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0656 The {0} '{1}' cannot be used as an Error


anchor because it is already defined in
the same '{2}'.

AL0657 The property {0} is mandatory for Error


ListParts and PageParts.

AL0658 Member name '{0}' is only allowed on Error


triggers.

AL0659 The length of the enum identifier '{0}' Warning


should not exceed {1} characters as it
may result in runtime issues in cases
where there are other enums with the
same first {1} characters.

AL0660 The property '{0}' cannot be Warning (Future Error)


customized.

AL0665 '{0}' is not a valid return type in Error


runtime version '{1}'. The supported
runtime versions are: {2}.

AL0666 '{0}' is not available in runtime version Error


'{1}'. The supported runtime versions
are: {2}.

AL0667 '{0}' is being deprecated in the Warning (Future Error)


versions: {1} {2}.

AL0668 This feature is not available on cross- Error


platform builds of the AL compiler.

AL0670 Fast publishing failed because the RAD Error


file has specified a non-existing
application object of type : '{0}' name:
'{1}' ID: '{2}' to be added or modified.
Please do a full publishing before
issuing a fast publishing again.

AL0671 Fast publishing failed because the RAD Error


file has specified an existing application
object of type: '{0}' name: '{1}' ID: '{2}'
to be deleted. Please do a full
publishing before issuing a fast
publishing again.

AL0672 Filtering is only allowed on fields where Error


FieldClass is set to Normal. Create a
Filter column and specify the filter by
using the 'ColumnFilter' property.

AL0673 The property '{0}' is required. Error


ID M ESSA GE DEFA ULT SEVERIT Y

AL0674 The property '{0}' is required when Error


property '{1}' is set to '{2}'.

AL0675 An implementation for the interface Error


'{0}' is already specified in this list.

AL0676 The member '{0}' in object '{1}' cannot Error


be declared as protected in object type
'{2}'.

AL0677 The member '{0}' in object '{1}' cannot Warning (Future Error)
be declared as protected in object type
'{2}'.

AL0679 The application object '{0}' is not Warning


included in any entitlement and will
therefore not be accessible in the
cloud.

AL0680 Cannot use addBefore or addAfter on Error


a top-level data item. The anchor {0} is
a top level data item.

AL0681 A DataItem with name '{0}' could not Error


be found in the target {1}.

AL0682 A DataItem or Column with name '{0}' Error


could not be found in the target {1}.

AL0683 The permissionset '{0}' belongs to a Error


different module and cannot be used
when defining entitlements.

AL0684 The permissionset '{0}' contains Warning


permissionsets or permission for
objects from other module.
Permissions on objects from other
modules will be ignored.

AL0685 The length '{0}' of the calculation Warning (Future Error)


formula's target field '{1}' is greater
than the length '{2}' of the source flow
field '{3}'. This could result in a runtime
error. Please make sure that the target
field's length is less than equal to the
source field length.

AL0686 The base type already defines a Error


method called '{0}' with the same
parameter types.

AL0687 The key '{0}' on table '{1}' cannot Error


contain the fields defined for the
primary key in the IncludeFields
property.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0688 The key '{0}' on table '{1}' cannot Error


contain the fields defined for the key in
the IncludeFields property.

AL0689 The key '{0}' on table '{1}' cannot Error


contain the fields defined for the
SqlIndex in the IncludeFields property.

AL0690 The primary key '{0}' on table '{1}' (the Error


first one in the key list) must not have
the IncludedFields property set.

AL0691 The primary key '{0}' on table '{1}' Error


cannot be obsolete. All related
properties will have no effect.

AL0692 The primary key '{0}' on table '{1}' Warning (Future Error)
cannot be obsolete. All related
properties will have no effect.

AL0693 The field '{0}' which is part of the Error


primary key of table '{1}' cannot be
obsolete. All related properties will
have no effect.

AL0694 The field '{0}' which is part of the Warning (Future Error)
primary key of table '{1}' cannot be
obsolete. All related properties will
have no effect.

AL0695 The method {0} will only be available Warning (Future Error)
for {1} development for runtime
version {2}.

AL0696 Argument {0}: The argument should be Error


a valid Field type.

AL0697 Argument {0}: The argument should be Warning (Future Error)


a valid Field type.

AL0698 Type {0} cannot be used in a 'case' Error


statement.

AL0700 Dependency '{0}' should be referenced Warning


in the property '{1}' rather than as an
explicit dependency.

AL0702 Dependency '{0}' is referenced in the Warning


property '{1}' and as an explicit
dependency. Remove the explicit
dependency.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0704 A layout must be specified through the Error


'ExcelLayout' property when the
default layout type for a report is
'Excel'.

AL0705 Another layout with name '{0}' already Error


exists.

AL0706 The property '{0}' cannot be used while Error


also specifying the rendering section.

AL0707 Layouts of type '{0}' must specify a Error


LayoutFile with one of the following
extensions: {1}.

AL0708 MimeType values must be less than {0} Error


characters in length.

AL0709 The layout file at path '{0}' specified in Error


layout '{1}' in {2} {3} does not exist.

AL0710 The DefaultRenderingLayout property Error


can only be used with layouts specified
in the report's rendering section.

AL0711 A member of type {0} with name '{1}' is Warning (Future Error)
already defined in {2} '{3}' by the
extension '{4}'. Duplicate member
names are not allowed when defining
CueActions.

AL0712 A member of type {0} with name '{1}' is Error


already defined in {2} '{3}' by the
extension '{4}'. Duplicate member
names are not allowed when defining
CueActions.

AL0713 Events in control add-ins should be Error


implemented as triggers.

AL0714 The name '{0}' is an Area type. Using Error


an Area type name will limit
extensibility as dependent extension
won't be able to reference it.

AL0715 The {0} name '{1}' is reserved for future Warning (Future Error)
AL language features.

AL0716 The {0} name '{1}' is reserved for future Error


AL language features.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0717 The property 'TableRelation' or the Warning


property 'CalcFormula' is required for
the field '{0}' in {1} '{2}' because the
field's property 'FieldClass' is set to
'FlowField'.

AL0718 Report layouts must have a name. Error

AL0719 Argument {0}: The argument should be Information


a valid Field type. An argument of type
Joker or Variant might have an
underlying type that is not a valid Field
type.

AL0720 An application object '{0} {1}' could not Error


be found in the extension.

AL0721 Reports that use the rendering syntax Error


must also define the
DefaultRenderingLayout property.

AL0722 The property '{0}' is not allowed on {1} Error


'{2}' because the {3} '{4}' is using the
ActionRef syntax or the app.json
specifies the
'NoPromotedActionProperties' feature.

AL0723 The {0} '{1}' cannot be used as target Error


of the ActionRef '{2}'. ActionRefs can
only target Actions.

AL0724 An area of type '{0}' is not valid on Error


pages of type '{1}'.

AL0725 The action type '{0}' is not allowed in Error


area '{1}'.

AL0726 An identifier, a literal, or an option Error


access is expected as the value of a
filter expression.

AL0727 The property '{0}' can only be set if the Warning (Future Error)
property '{1}' is set.

AL0728 The property '{0}' can only be set if the Warning (Future Error)
property '{1}' is set to '{2}'.

AL0729 The property '{0}' can only be set if the Warning (Future Error)
property '{1}' is set with any of the
values of: '{2}'.

AL0730 The field '{0}' cannot be used in a sum Error


index.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0731 The name '{0}' does not exist in the Warning (Future Error)
current context.

AL0732 Access modifier '{0}' is not allowed for Error


member '{1}' in the context of object
type '{2}'.

AL0733 Access modifier '{0}' is not allowed for Warning (Future Error)
member '{1}' in the context of object
type '{2}'.

AL0734 The value '{0}' of the property '{1}' is Error


not a valid GUID.

AL0735 The custom action '{0}' cannot be Error


defined in {1} '{2}' because '{2}' uses
promoted action properties. Convert
the promoted properties into
ActionRefs in oder to use custom
actions.

AL0736 The value '{0}' of the property Error


'FlowEnvironmentId' is not a valid. It
must either be a GUID or must match
the pattern 'Default-'.

AL0737 The {0} '{1}' cannot be referenced in {2} Error


'{3}' because '{1}' is defined in the
promoted part of the action part while
'{3}' uses promoted action properties.

AL0738 The name of {0} '{1}' cannot be empty. Error

AL0739 The name of {0} '{1}' cannot be empty. Warning

AL0740 The permission set '{0}' cannot be Error


excluded and included in the same
permission set.

AL0741 The permission set '{0}' cannot exclude Error


itself.

AL0742 The property '{0}' is not valid for the Error


cue action '{1}'.

AL0743 The property '{0}' is not valid for the Warning (Future Error)
cue action '{1}'.

AL0744 The property '{0}' is not valid for action Error


'{1}' defined in a report request page.

AL0745 The property '{0}' is not valid for action Warning (Future Error)
'{1}' defined in a report request page.
ID M ESSA GE DEFA ULT SEVERIT Y

AL0746 The auto-increment field '{0}' has Error


already been defined for table '{1}'.

AL0748 The return type '{0}' of the {1} method Warning


'{2}' has 'Internal' accessibility. The
return value will not be usable outside
of this module without an implicit
conversion.

AL0749 The type '{0}' of the parameter '{1}' of Warning


the {2} method '{3}' has 'Internal'
accessibility. The method will not be
callable outside of this module without
an implicit conversion.

AL0750 Enum values can't be nested. Use '{0}' Error


instead.

AL0751 Enum values can't be nested. Use '{0}' Warning (Future Error)
instead.

AL0752 The name of a dataitem cannot be Error


empty because it can cause runtime
errors.

AL0753 The name of a dataitem cannot be Warning (Future Error)


empty because it can cause runtime
errors.

AL0754 The '{0}' already defines a method Error


called '{1}'.

AL0755 The '{0}' already defines a method Warning (Future Error)


called '{1}'.

AL0756 The division by Abs(integer) will Warning


change its behavior in release version
11. For more information visit the
official documentation.

AL0757 The name of {0} '{1}' conflicts with {0} Error


'{2}' defined in {3} '{4}' by the extension
'{5}'. Please choose another name for
one of them. Otherwise, this might
cause runtime issues.

AL0758 The name of {0} '{1}' conflicts with {0} Warning (Future Error)
'{2}' defined in {3} '{4}' by the extension
'{5}'. Please choose another name for
one of them. Otherwise, this might
cause runtime issues.

AL0999 Internal error: {0}. Error


ID M ESSA GE DEFA ULT SEVERIT Y

AL1000 Ignoring /noconfig option because it Warning


was specified in a response file.

AL1001 Source file '{0}' could not be found. Error

AL1002 Error opening response file '{0}'. Error

AL1003 An instance of analyzer {0} cannot be Warning


created from {1} : {2}.

AL1004 The assembly {0} does not contain any Warning


analyzers.

AL1005 Unable to load Analyzer assembly {0} : Warning


{1}.

AL1006 Metadata file '{0}' could not be found. Error

AL1007 Missing file specification for '{0}' Error


option.

AL1008 Command-line syntax error: Missing Error


'{0}' for '{1}' option.

AL1009 Unrecognized option: '{0}'. Error

AL1010 Command-line syntax error: Missing Error


:<number> for '{0}' option.

AL1011 Source file '{0}' specified multiple times. Warning

AL1012 Could not write to output file '{0}' -- Error


'{1}'.

AL1013 '{0}' is a binary file instead of a text file. Error

AL1014 Source file '{0}' could not be opened -- Error


{1}.

AL1015 Compilation canceled by user. Error

AL1017 The manifest file is not valid. {0}. Error

AL1018 Directory '{0}' could not be found. Error

AL1019 One or more dependencies defined in Error


the project manifest are not valid. One
or more of the required attributes:
'publisher', 'name', 'version', and 'id' are
either missing or not valid.

AL1021 The package cache path has not been Error


specified.
ID M ESSA GE DEFA ULT SEVERIT Y

AL1022 A package with publisher '{0}', name Error


'{1}', and a version compatible with '{2}'
could not be found in the package
cache folder '{3}'.

AL1023 The package file {0} is not valid. Error

AL1024 A package with publisher '{0}', name Error


'{1}', and a version compatible with '{2}'
could not be loaded. {3}.

AL1025 The file at location '{0}' does not match Warning


any definition.

AL1026 A warning occurred during XML Warning


validation: '{0}'.

AL1028 An IO exception has happened when Error


trying to write to output file '{0}' --
'{1}'.

AL1029 Translation file '{0}' has invalid target Warning


language '{1}'.

AL1030 Translation file '{0}' is missing a target Warning


language.

AL1031 Successfully included translations for: Information


{0}.

AL1032 Translation file '{0}' has the same target Error


language as another translation file.

AL1033 An error occurred while loading the Error


included rule set file {0} - {1}.

AL1034 The link '{0}' must contain a Error


placeholder with value 0 for the user
locale.

AL1035 The manifest properties 'baseHelpUrl' Error


and 'supportedLocales' must both be
specified and have values.

AL1036 The locale '{0}' is not valid. Error

AL1037 The locale '{0}' is already defined. Error

AL1038 The version number '{0}' for the Error


property '{1}' does not match the
expected format: W.X.Y.Z where W, X, Y,
and Z represent positive integers.
ID M ESSA GE DEFA ULT SEVERIT Y

AL1039 The version number '{0}' for the Error


property '{1}' does not match the
expected format: X.Y where X and Y
represent positive integers.

AL1040 The guid number '{0}' does not match Error


the expected pattern: "^[0-9a-fA-F]
{{8}}-[0-9a-fA-F]{{4}}-[0-9a-fA-F]{{4}}-
[0-9a-fA-F]{{4}}-[0-9a-fA-F]{{12}}$".

AL1041 The property '{0}' must be defined in Error


the manifest.

AL1042 The id '{0}' for the package with Error


publisher '{1}', name '{2}', and version
'{3}' specified in the project manifest
does not match the id '{4}' of the
package with the same name,
publisher, and version found in the
package cache folder.

AL1043 The runtime version '{0}' is not Error


supported by the AL compiler.

AL1044 The value for the manifest property Error


'{0}' is not valid. Expected type: {1}.

AL1045 The package cache {0} could not be Error


found.

AL1046 The application ID ranges {0} are Error


overlapping.

AL1047 The application ID range {0} is not Error


valid.

AL1048 Both 'idRange' and 'idRanges' Error


properties are added. You should use
the 'idRanges' property and remove
the 'idRange' property.

AL1049 A project without a manifest must Error


have the /out option specified.

AL1050 Fast publishing requires an application Error


file '{0}' to be build and published.

AL1051 Fast publishing requires that there are Error


no manifest changes for the
application '{0}'.

AL1052 The link '{0}' can only contain one Error


placeholder with value 0 for the user
locale. No other placeholder values are
allowed.
ID M ESSA GE DEFA ULT SEVERIT Y

AL1053 The value '{0}' is not valid for the Error


manifest property '{1}'.

AL1054 Invalid reference module: {0}. Error

AL1055 Invalid reference module: {0}. Warning

AL1056 A package with publisher '{0}', name Warning


'{1}', and a version compatible with '{2}'
could not be loaded. {3}.

AL1057 The module specification is not valid. Error


One or more of the required
attributes: 'publisher', 'name', and 'id'
are either missing or not valid.

AL1058 appId and Id are both specified for a Warning


dependency property. The appId value
will be ignored.

AL1059 Feature '{0}' can only be enabled, if Warning


feature '{1}' is also enabled.

AL1060 The max degree of parallelism must be Error


-1 or positive.

AL1061 An error occurred during file validation: Error


'{0}'.

AL1062 Too many key vault URLs specified. Error

AL1063 Key vault URL is too long. Error

AL1064 Key vault URL is not a valid Azure key Error


vault URL. A valid key vault URL must
use HTTPS and point to the Azure key
vault domain.

AL1065 Key vault URL should not have a path Error


or query string.

AL1066 Duplicate package dependency with Error


application ID '{0}', publisher '{1}', and
name '{2}'. Remove duplicate
dependencies in the application
manifest.

AL1067 Duplicate package dependency with Error


publisher '{0}', and name '{1}'. Remove
duplicate dependencies in the
application manifest.
ID M ESSA GE DEFA ULT SEVERIT Y

AL1068 Duplicate package dependency with Error


application ID '{0}', and publisher '{1}'.
Remove duplicate dependencies in the
application manifest.

AL1069 Duplicate package dependency with Error


application ID '{0}', and name '{1}'.
Remove duplicate dependencies in the
application manifest.

AL1070 Duplicate package dependency with Error


application ID '{0}'. Remove duplicate
dependencies in the application
manifest.

AL1071 Error writing to XML documentation Error


file: {0}.

AL1072 The name for the preprocessing Warning


symbol is not valid; '{0}' is not a valid
identifier.

AL1073 The procedure with name {0} has the Error


same name as a declared trigger.

AL1074 Both 'applicationInsightsKey' and Error


'applicationInsightsConnectionString'
are added. You should use the
'applicationInsightsConnectionString'
property and remove the
'applicationInsightsKey' property.

AL1075 Both 'ShowMyCode' and Error


'ResourceExposurePolicy' properties are
added. You should use the
'ResourceExposurePolicy' property and
remove the 'ShowMyCode' property.

AL1076 A package that satisfies the Information


dependency on app with ID {0} with
name '{1}' and publisher '{2}' was
found, but the name or publisher has
changed. New name '{3}' and new
publisher '{4}'. Consider updating the
dependency reference to the new
name/publisher.

AL1077 An error was encountered when trying Error


to load the workspace: {0}.

AL1078 Key vault URL is not a valid Azure key Warning (Future Error)
vault URL. A valid key vault URL must
use HTTPS and point to the Azure key
vault domain.
ID M ESSA GE DEFA ULT SEVERIT Y

AL1079 Debugging will not work for this Information


extension because 'allowDebugging'
has been set to false and
'applyToDevExtension' to true.

AL1080 Source will still be visible for this Information


extension via debugging because
'allowDebugging' has been set to true.

AL1100 File name '{0}' is empty, contains Fatal Error


invalid characters, has a drive
specification without an absolute path,
or is too long.

AL1101 Target must specify one of: 'internal', Fatal Error


'solution', 'extension'.

AL1130 The format of property '{0}' must be a Error


timeout duration specified as
'[d.]hh:mm:ss[.fffffff]'.

AL1150 The link in parameter '{0}' ({1}) is not Error


valid. {2}.

AL1151 Cannot create a manifest for Extension Error


"{0}" because the Name and Publisher
match the current application. Remove
this dependency from the application
manifest.

AL1152 Dependency with ID '{0}' matches the Error


current application ID. Remove this
dependency from the application
manifest.

AL1401 Reference '{0}' in application object '{1}' Designer Customization Warning


does not exist.

AL1402 {0} '{1}' is missing. Designer Customization Warning

AL1403 '{0}' is an ambiguous reference Designer Customization Warning


between '{1}' defined by the extension
'{2}' and '{3}' defined by the extension
'{4}'.

AL1404 The action '{0}' is not found in the Designer Customization Warning
target '{1}'.

AL1405 The control '{0}' is not found in the Designer Customization Warning
target '{1}'.

AL1406 The view '{0}' is not found in the target Designer Customization Warning
'{1}'.
ID M ESSA GE DEFA ULT SEVERIT Y

AL1407 At least one target has to be specified Designer Customization Warning


for the move.

AL1408 Invalid application object identifier. A Designer Customization Warning


number or an application object name
is expected.

AL1409 Page '{0}' should be of type Designer Customization Warning


'RoleCenter'.

AL1410 The target {0} {1} for the extension Designer Customization Warning
object is not found.

AL1411 Multiple page customizations have Designer Customization Warning


been specified for the same page {0}
within the same profile.

AL1412 {0} '{1}' is marked for removal. {2}. Designer Customization Warning

AL1413 A member of type {0} with name '{1}' is Designer Customization Warning
already defined in {2} '{3}' by the
extension '{4}'.

AL1414 The page customization for page '{0}' Designer Customization Information
does not make any modifications, so it
can be removed without affecting any
profiles or user personalization.

AL1415 {0} '{1}' is removed. {2}. Designer Customization Warning

AL1416 The {0} '{1}' cannot be moved relatively Designer Customization Information
to '{2}' because '{2}' is missing. This
move is ignored.

AL1417 The {0} '{1}' cannot be added relatively Designer Customization Information
to '{2}' because '{2}' is missing. '{1}' is
added at a default location instead.

AL1418 A DataItem with name '{0}' could not Designer Customization Warning
be found in the target {1}.

AL1419 A DataItem or Column with name '{0}' Designer Customization Warning


could not be found in the target {1}.

AL1420 The {0} '{1}' cannot be used as target Designer Customization Warning
of the ActionRef '{2}'. ActionRefs can
only target Actions. Ignoring the
ActionRef.

AL1421 The {0} '{1}' is using the '{2}' property. Designer Customization Warning
This will be automatically converted to
the new syntax when customizing the
related page in the webclient.
ID M ESSA GE DEFA ULT SEVERIT Y

AL1422 The target action '{0}' cannot be Designer Customization Warning


resolved in page '{1}'. Ignoring the
ActionRef.

See Also
Get Started with AL
Developing Extensions
Ruleset for the Code Analysis Tool
2/6/2023 • 2 minutes to read • Edit Online

In an AL project, you can use a custom ruleset file to specify how code analysis will report the issues it
encounters. Different settings can affect how rules are applied and each ruleset file name must follow the
pattern <name>.ruleset.json to benefit from IntelliSense in Visual Studio Code.

NOTE
Use the truleset and trule snippets provided by the AL Language extension to create your ruleset.

The following table describes the schema of a ruleset object:

SET T IN G M A N DATO RY TYPE VA L UE

name Yes String The name of the ruleset.

description No String The description of the


ruleset. You can use this
setting to document the
purpose of the ruleset.

generalAction No Error | Warning | Info | Hidd The action to apply to all


en the diagnostics that have
rules defined in this file or in
other files that have a
Default action specified. It
also applies to all the
diagnostics generated by
the current set of analyzers
that don't have a rule
defined. If an included file
has a stricter
generalAction , that one
will be used.

includedRuleSets No Array of IncludedRuleSet List of external ruleset files


to include in the current
ruleset. The order in which
the files are processed is
undefined.

rules No Array of Rule Collection of rules to apply


to diagnostics generated by
analyzers.

An IncludedRuleSet is a complex JSON object that defines the inclusion of an external ruleset file in the
current ruleset, and has the following properties:

SET T IN G M A N DATO RY TYPE VA L UE


SET T IN G M A N DATO RY TYPE VA L UE

path Yes String The path to the included


file. For includes specified in
the file to which the
al.ruleSetPath is set, the
path can be absolute or
relative to the project folder.
For files included from the
root ruleset file, the path is
relative to the file. Adding
an entry to the ruleset path
and saving it, will
automatically be applied to
all the projects that are
using the ruleset.

action Yes Error | Warning | Info | Hidd The action to apply for all
en | None | Default the diagnostics that have
an action specified in the
included ruleset that is
different from None and
Hidden .

A Rule is a complex JSON object that defines how you can process a specific diagnostic. A Rule object has the
following properties:

SET T IN G M A N DATO RY TYPE VA L UE

id Yes String The string that uniquely


identifies a diagnostic.

action Yes Error | Warning | Info | Hidd The action to apply if the
en | None diagnostic is emitted. There
can't be two rules with the
same id and different
actions in the same rule file.

Examples
The following example shows a ruleset that sets the severity of rule AA0001 : There must be exactly one
space character on each side of a binar y operator such as := + - AND OR =. provided by the
CodeCop analyzer to Error .

{
"name": "Company ruleset",
"description": "These rules must be respected by all the AL code written within the company.",
"rules": [
{
"id": "AA0001",
"action": "Error",
"justification": "This diagnostic helps to improve readability. It must be respected in all
cases."
}
]
}

The following example shows a project-specific ruleset that extends a company-wide ruleset contained in the file
company.ruleset.json and sets the severity of the rule AA0005 : Only use BEGIN..END to enclose
compound statements. provided by the CodeCop analyzer to Info .

{
"name": "Personal Project ruleset",
"description": "A list of project specific rules",
"includedRuleSets": [
{
"action": "Default",
"path": "./company.ruleset.json"
}
],
"rules": [
{
"id": "AA0005",
"action": "Info",
"justification": "For this specific project, this diagnostic should be informational."
}
]
}

See Also
Using the Code Analysis Tools
Using the Code Analysis Tools with the ruleset
AL Development Environment
Directives in AL
AL Language Extension Configuration
Using the Code Analysis Tools with the Ruleset
2/6/2023 • 3 minutes to read • Edit Online

This article helps you to customize a ruleset for the severity of diagnostics produced by the code analysis tools
that are part of the AL Language extension for Visual Studio Code.

Use rulesets with code analysis


First, create a basic project in AL by following the steps below:
1. Press Alt + A, Alt + L to create a new project.
2. Open the Command Palette by using the Ctrl+Shift+P shortcut and choose either User Settings or
Workspace Settings .
3. Under Extensions , go to Al Language extension configuration . When you scroll down, you'll find Code
Analyzers section, choose Edit in settings.json .
4. Set the al.enableCodeAnalysis in the settings file to true .
"al.enableCodeAnalysis": true
5. In the al.codeanalyzers setting, use Ctrl+Space to pick from the available code analyzers. Separate the list
of code analyzers with commas. For more information about the available analyzers, see AppSourceCop,
CodeCop, PerTenantExtensionCop, and UICop.
At this point, the selected analyzers will run on your project. Next, add some code to the project that will, in the
following example, be used to demonstrate violations of the AA0001 "There must be exactly one space
character on each side of a binar y operator such as := + - AND OR =." code analysis rule.

Add your own code to the project


In the Visual Studio Code Explorer, open the HelloWorld.al file and replace the existing code with the following
code:

pageextension 50100 CustomerListExt extends "Customer List"


{
trigger OnOpenPage();
var
result: Integer;
begin
// The following line will trigger the warning
// AA0001 "There must be exactly one space character on each side
// of a binary operator such as := + - AND OR =."
result := 2+2;
Message('2 + 2 = ' + Format(result));
end;
}

On the View tab of Visual Studio Code, select the Problems option and you'll see a warning with the message
"There must be exactly one space character on each side of '+'." . In this case, the problem can be fixed
by running the AL Formatter command. For more information, see AL Formatter.

Create and customize a ruleset


To create and customize a ruleset of your own, follow the next steps:
1. On the File tab in Visual Studio Code, choose New File .
2. Save the empty file with a name, for example <name>.ruleset.json and make a note of the file path.
3. Add the following code to the <name>.ruleset.json file:

{
"name": "My Custom ruleset",
"rules": [
{
"id": "AA0001",
"action": "None"
}
]
}

4. In your project settings, set Rule Set Path to the path of the <name>.ruleset.json file, relative to the
project root. For more information about custom rules, see Ruleset for the Code Analysis Tool.

NOTE
Use the truleset and trule snippets provided by the AL Language extension to create your ruleset. The ruleset will
be applied to all the analyzers enabled for the current project. For more information about selectively enabling analyzers,
see The Code Analysis Tools.

Running the code analysis


The code analysis will run in the background and you'll see the warning "There must be exactly one space
character on each side of '+'." disappear from the Problems option in Visual Studio Code.
To trigger a new compilation manually, use the Ctrl+Shift+B shortcut to build your project. For more
information about AL keyboard shortcuts, see Keyboard shortcuts.

Limitations
Changing the contents of the ruleset file won't be detected by the AL Language extension. To see the effects of
changing the ruleset file, you can try any of the following steps:
Reload the window.
In the project settings, change the Rule Set Path setting to an invalid path and save it. Then change it back
and save again.

See also
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools
Directives in AL
Development in AL
Debugging in AL
AL Language Extension Configuration
AppSourceCop Analyzer Rules
2/6/2023 • 10 minutes to read • Edit Online

AppSourceCop is an analyzer that enforces rules that must be respected by extensions meant to be published to
Microsoft AppSource.

Rules
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0001 Tables and table extensions Upgrade Error


that have been published
must not be deleted.

AS0002 Fields must not be deleted. Upgrade Error

AS0003 The previous version of the Upgrade Error


extension could not be
found.

AS0004 Fields must not change Upgrade Error


type, since dependent
extensions may break

AS0005 Fields must not change Upgrade Error


name

AS0006 Tables that have been Upgrade Error


published must not change
name.

AS0009 Key fields must not be Upgrade Error


changed

AS0010 Keys must not be deleted Upgrade Error

AS0011 An affix is required Extensibility Error

AS0013 The field identifier must be Extensibility Error


within the allowed range

AS0014 The project manifest must Extensibility Error


contain the allocated
identifier range

AS0015 TranslationFile must be Extensibility Error


enabled.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0016 Fields of field class 'Normal' Extensibility Error


must use the
DataClassification property
and its value should be
different from ToBeClassified

AS0018 A procedure belonging to Upgrade Error


the public API cannot be
removed

AS0019 Event attributes cannot be Upgrade Error


removed

AS0020 The type of events cannot Upgrade Error


be changed.

AS0021 An argument in an event Upgrade Error


attribute cannot be
changed to false.

AS0022 An external scope cannot Upgrade Error


be removed

AS0023 A return type cannot be Upgrade Error


modified in external
procedures

AS0024 Parameters cannot be Upgrade Error


removed or added in
external procedures

AS0025 Parameters cannot be Upgrade Error


modified, renamed, or
removed from events.

AS0026 The type and subtype of Upgrade Error


parameters cannot be
modified in events and
external procedures

AS0027 Modifying the array size of Upgrade Error


a parameter in events and
external procedures is not
allowed

AS0028 Reducing the array size of a Upgrade Error


parameter in events and
external procedures is not
allowed

AS0029 Pages and PageExtensions Upgrade Error


that have been published
must not be deleted, since
dependent extensions may
break
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0030 Pages that have been Upgrade Error


published must not be
renamed.

AS0031 Actions that have been Upgrade Error


published must not be
deleted.

AS0032 Controls that have been Upgrade Error


published must not be
deleted.

AS0033 Views that have been Upgrade Error


published must not be
deleted.

AS0034 Unsupported table Upgrade Error


property change

AS0036 Unsupported table field Upgrade Error


property change

AS0038 Unsupported table key Upgrade Error


property change

AS0039 Removing properties that Upgrade Error


cause destructive changes is
not allowed

AS0041 Table field property changes Upgrade Error


that cause destructive
changes must not be
removed

AS0042 Table key property changes Upgrade Error


that cause destructive
changes must not be
removed

AS0043 The clustered key must not Upgrade Error


be deleted

AS0044 Property changes that Upgrade Error


cause destructive changes
are not allowed

AS0047 The extension name is too Extensibility Error


long.

AS0048 The publisher name is too Extensibility Error


long.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0049 The access modifier of an Extensibility Error


application object cannot be
changed to a value that
provides less access.

AS0050 The extensibility of an Extensibility Error


application object cannot be
removed

AS0051 Manifest property is Extensibility Error


required for AppSource
submission

AS0052 The property 'url' must be Extensibility Error


set to a valid URL

AS0053 The compilation target of Extensibility Error


an application must be a
value that is allowed in a
multi-tenant SaaS
environment

AS0054 The AppSourceCop Configuration Error


configuration must specify
the set of affixes used by
the application

AS0055 The AppSourceCop Configuration Hidden


configuration must specify
the list of countries/regions
targeted by the application

AS0056 The country/region codes Configuration Warning


specified in the
'supportedCountries'
property must be valid ISO
3166-1 alpha-2 codes

AS0057 Translations must be Extensibility Hidden


provided for all the locales
in which the application will
be available

AS0058 Only use AssertError in Test Extensibility Error


Codeunits

AS0059 Reserved database tables Extensibility Error


are read-only in a multi-
tenant environment

AS0060 Unsafe methods cannot be Extensibility Error


invoked in an AppSource
application
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0061 Procedures must not Extensibility Error


subscribe to CompanyOpen
events

AS0062 Page controls and actions Extensibility Error


must use the
ApplicationArea property

AS0063 Removing a var modifier in Upgrade Error


events is not allowed

AS0064 Interface implementations Upgrade Error


that have been published
must not be deleted.

AS0065 Interfaces that have been Upgrade Error


published must not be
deleted.

AS0066 A new method to an Upgrade Error


interface that has been
published must not be
added.

AS0067 Adding an interface to an Upgrade Error


enum that has been
published must have a
default implementation.

AS0068 Changing a table Upgrade Error


extension's target is not
allowed.

AS0069 An enum field replacing an Upgrade Error


option field should have at
least the same number of
members.

AS0070 An enum field replacing an Upgrade Error


option field should preserve
the member names.

AS0071 An enum field replacing an Upgrade Error


option field should preserve
the member ordinal values.

AS0072 The ObsoleteTag property Design Hidden


and the Tag in the Obsolete
attribute must be set to the
next release version.

AS0073 Obsolete Tag must be set. Design Hidden

AS0074 The Obsolete Tag must be Design Hidden


the same across branches.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0075 Obsolete Reason must be Design Warning


set.

AS0076 Obsolete Tag format. Design Hidden

AS0077 Adding a var modifier in Upgrade Error


events is not allowed

AS0078 Adding or removing a var Upgrade Error


modifier in external
procedures is not allowed

AS0079 An affix is required for Extensibility Warning


procedures defined in
extension objects.

AS0080 Fields must not decrease in Upgrade Error


length

AS0081 InternalsVisibleTo should Extensibility Warning


not be used as a security
feature.

AS0082 It is not allowed to rename Upgrade Error


an enum value.

AS0083 It is not allowed to delete a Upgrade Error


value from an enum.

AS0084 The ID range assigned to Extensibility Error


the extension must be
within the allowed range

AS0085 The 'application' property Extensibility Warning


should be used instead of
explicit dependencies

AS0086 Fields must not increase in Upgrade Warning


length

AS0087 Translations of enum value Extensibility Warning


captions must not contain
commas

AS0088 Objects with an ID that can Upgrade Error


be referenced and which
have been published must
not be deleted.

AS0089 Objects that can be Upgrade Error


referenced and which have
been published must not be
deleted.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0090 Objects that can be Upgrade Error


referenced and which have
been published must not be
renamed.

AS0091 One or more dependencies Upgrade Error


of the previous version of
the extension could not be
found.

AS0092 The app.json file must Configuration Warning


specify an Azure Application
Insights resource.

AS0094 Permission Sets should not Configuration Warning


be defined in XML files.

AS0095 The access modifier of a Configuration Error


table field cannot be
changed to a value that
provides less access.

AS0096 The name of an extension Configuration Error


cannot be changed.

AS0097 The publisher name of an Configuration Error


extension cannot be
changed.

AS0098 An affix is needed. Extensibility Warning

AS0099 The member ID should be Extensibility Info


within the allowed range

AS0100 The 'application' property in Extensibility Error


the app.json file must be
specified.

AS0101 The 'Isolated' argument Upgrade Error


cannot be changed, added,
or removed.

AS0102 Cannot add a return value Upgrade Error


to a procedure

AS0103 Table definitions must have Configuration Warning


a matching permission set.

AS0104 The extension name is not Extensibility Error


valid.

AS0105 Object pending obsoletion Design Error


contains an expired
ObsoleteTag.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0106 A variable belonging to the Design Error


public API cannot be
removed.

AS0107 The access modifier of a Design Error


variable that belongs to the
public API cannot be
changed to a value that
provides less access.

AS0108 The type of a variable Design Error


belonging to the public API
cannot be changed.

AS0109 The type of the table has Upgrade Warning


changed from Normal to
Temporary.

NOTE
Several rules enforced by the AppSourceCop analyzer are incompatible with rules enforced by the PerTenantExtensionCop.
Make sure to enable only one of these at a time.

NOTE
Failing to comply with the rules whose default severity is set to Error will fail the submission of your extension to the
AppSource marketplace. It is recommended, but not mandatory to comply with the rules whose severity is marked as
Warning or Info .

Configuration
The AppSourceCop analyzer can be further configured by adding a file named AppSourceCop.json in the
project's root folder. The AL Language extension will offer IntelliSense for this file.
The following table describes the settings in the AppSourceCop.json file:

SET T IN G M A N DATO RY VA L UE

name No The name of a previous version of this


package with which you want to
compare the current package for
breaking changes.

publisher No The publisher of a previous version of


this package with which you want to
compare the current package for
breaking changes.

version Yes The version of a previous version of


this package with which you want to
compare the current package for
breaking changes.
SET T IN G M A N DATO RY VA L UE

mandatoryAffixes No Affixes that must be prepended or


appended to the name of all new
application objects, extension objects,
and fields.

supportedCountries No The set of country codes, in the alpha-


2 ISO 3166 format, in which the
application will be available.

targetVersion No Specifies the next Major.Minor version


of the extension in the current branch
in order to validate the ObsoleteTag
values with AS0072. This is only
relevant when the default
obsoleteTagPattern '(\d+)\.(\d+)' is
used. This property is being
deprecated in favor of
obsoleteTagVersion.

obsoleteTagVersion No Specifies the next Major.Minor version


of the extension in the current branch
in order to validate the ObsoleteTag
values with AS0072. This is only
relevant when the default
obsoleteTagPattern '(\d+)\.(\d+)' is
used.

obsoleteTagPattern No The Obsolete tag pattern used by


AS0076. This should be a valid regular
expression. By default, the pattern
'(\d+)\.(\d+)' is used.

obsoleteTagPatternDescription No A human-readable description for the


ObsoleteTagPattern regular expression.
This is used in diagnostics reported by
AS0076. By default, 'Major.Minor' is
used.

obsoleteTagAllowedVersions No A comma-separated list of Major.Minor


versions that will be allowed as
ObsoleteTag values by AS0072. This is
only relevant when the default
obsoleteTagPattern '(\d+)\.(\d+)' is
used.

baselinePackageCachePath No The path to the folder containing the


baseline and its dependencies with
which you want to compare the
current package for breaking changes.
By default, the package cache path for
the current project is used (see
'al.packageCachePath' setting).
SET T IN G M A N DATO RY VA L UE

obsoleteTagMinAllowedMajorMinor No The minimum version of ObsoleteTag


(Major.Minor) allowed during
compilation. Referencing an obsolete
pending object with an obsolete tag
lower than the specified version will
trigger the rule AS0105. Note that
enabling this setting has a
performance impact.

The name , publisher , version properties are used for specifying a previous version of the current package.
This package must be located in the baseline package cache folder of your extension. This cache can be specified
using the baselinePackageCachePath property. If this property is not specified, the dependency package cache
path of the extension will be used instead. The al.packageCachePath setting allows you to specify the path to the
folder that will act as the cache for the dependencies symbol files used by your project. AppSourceCop will
compare the previous version of your extension with its current version and will report any breaking changes
introduced by the current package.
The mandatoryAffixes property specifies strings that must be prepended or appended to the names of all new
objects, extension objects and fields. By using these affixes, you can prevent clashes between objects added by
your extension and objects added by other extensions.
The supportedCountries property specifies the codes that correspond to the countries for which the product
allows AppSource submissions. For more information, see Availability and supported Countries/Regions and
Translations
The properties obsoleteTagVersion , obsoleteTagPattern , and obsoleteTagPatternDescription can be used to
enable additional validation on object obsoletion. These are not required for AppSource submissions.

Example
In the following example, we will configure AppSourceCop to validate that all new elements have a name that
contains one of the specified affixes.

NOTE
Make sure that code analysis is enabled and ${AppSourceCop} is specified in the list of enabled code analyzers. For more
information see AL Language Extension Configuration.

We start by creating the default "Hello world" extension.

pageextension 50100 CustomerListExt extends "Customer List"


{
trigger OnOpenPage();
begin
begin
Message('App published: Hello world');
end;
end;
}

We continue by adding the configuration file AppSourceCop.json in the project's root folder and setting its
content to the following.
{
"mandatoryAffixes": [ "Foo", "Bar" ]
}

IMPORTANT
If you are running a multi-root workspace environment, you must have one AppSourceCop.json file in the root folder of
each of the projects. For more information, see Working with multiple AL project folders within one workspace.

You are immediately greeted by the following error message:

AS0011: The identifier 'CustomerListExt' must have at least one of the mandatory affixes 'Foo, Bar'.

Prepending Foo to the name of the page extension object will fix this error and prevent clashes between this
page extension and page extensions added by other developers.

NOTE
It is still possible to use the mandatoryPrefix and mandatorySuffix properties in the AppSourceCop.json . For more
information see AS0011.

See Also
Using the Code Analysis Tool
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools with the Ruleset
CodeCop Analyzer Rules
2/6/2023 • 5 minutes to read • Edit Online

CodeCop is an analyzer that enforces the official AL Coding Guidelines.

Rules
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0001 There must be exactly one Readability Warning


space character on each
side of a binary operator
such as := + - AND OR =.

AA0002 There must be no space Readability Warning


character.

AA0003 There must be exactly one Readability Warning


space character between
the NOT operator and its
argument.

AA0005 Only use BEGIN..END to Readability Warning


enclose compound
statements.

AA0008 Function calls should have Readability Warning


parenthesis even if they do
not have any parameters.

AA0013 When BEGIN follows THEN, Readability Warning


ELSE, DO, it should be on
the same line, preceded by
one space character.

AA0018 The END, IF, REPEAT, UNTIL, Readability Warning


FOR, WHILE, and CASE
statement should always
start a line.

AA0021 Variable declarations should Readability Warning


be ordered by type.

AA0022 Substitute the IF THEN ELSE Readability Warning


structure with a CASE.

AA0040 Avoid using nested WITH Readability Warning


statements.

AA0072 The name of variables and Readability Info


parameters must be
suffixed with the type or
object name.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0073 The name of temporary Readability Warning


variable must be prefixed
with Temp.

AA0074 TextConst and Label Readability Warning


variable names should have
an approved suffix.

AA0087 Lowering permissions Design Warning


should only be used in tests

AA0100 Do not have identifiers with Design Warning


quotes in the name.

AA0101 Use camel case property Design Warning


values in pages of type API.

AA0102 Use camel case name for Design Warning


field controls in pages of
type API.

AA0103 Use camel case property Design Warning


values in queries of type
API.

AA0104 Use camel case name for Design Warning


column controls in queries
of type API.

AA0105 PagePart controls must not Design Error


refer to parent pages.

AA0106 A page of type API can only Design Error


refer to the same subpage
once.

AA0131 String parameters must Design Warning


match placeholders.

AA0136 Do not write code that will Design Warning


never be hit.

AA0137 Do not declare variables Design Warning


that are unused.

AA0139 Do not assign a text to a Design Warning


target with smaller size.

AA0150 Do not declare parameters Design Warning


by reference if their values
are never changed.

AA0161 Only use AssertError in Test Design Warning


Codeunits.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0175 Only find record if you need Design Warning


to use it.

AA0181 The FindSet() or Find() Design Warning


methods must be used only
in connection with the
Next() method.

AA0189 Only use a correct values of Design Warning


ApplicationArea.

AA0194 Only write actions that have Design Warning


an effect.

AA0198 Do not use identical names Design Warning


for local and global
variables.

AA0199 Use only a correct order for Design Warning


ApplicationArea.

AA0200 When ApplicationArea is set Design Warning


to 'All', no other values for
ApplicationArea should be
specified.

AA0201 When ApplicationArea is set Design Warning


to 'Basic', you must also
specify 'Suite'.

AA0462 The CalcDate should only Localizability Warning


be used with DataFormula
variables. Alternatively the
string should be enclosed
using the <> symbols.

AA0202 To avoid confusion, do not Design Warning


give local variables the
same name as fields,
methods, or actions in the
same scope.

AA0203 To avoid confusion, do not Design Warning


give methods the same
name as fields or actions in
the same scope.

AA0204 To avoid confusion, do not Design Warning


give global variables the
same name as fields,
methods, or actions in the
same scope.

AA0205 Variables must be initialized Design Warning


before usage.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0206 The value assigned to a Design Warning


variable must be used.

AA0207 The EventSubscriber Design Warning


method must be local.

AA0210 Avoid non-indexed fields Design Info


into filtering.

AA0211 Avoids a runtime error from Design Warning


using CalcFields on a field
that is not a FlowField or a
field of type Blob.

AA0213 Obsoleted object must have Design Warning


a state 'Pending' or
'Removed' and a
justification specifying why
this field is being obsoleted.

AA0214 The local record should be Design Warning


modified before saving to
the database.

AA0215 Follow the style guide Readability Warning


about the best practices for
naming.

AA0216 Use a text constant for Localizability Warning


passing user messages and
errors without
concatenations.

AA0217 Use a text constant or label Localizability Warning


for format string in
StrSubstNo.

AA0218 You must write a tooltip in Localizability Warning


the Tooltip property for all
controls of type Action and
Field that exist on page
objects.

AA0219 The Tooltip property of Localizability Warning


Fields must start with
'Specifies'.

AA0220 The value of the Tooltip Localizability Warning


property of Fields must be
filled.

AA0221 You must specify a Localizability Warning


OptionCaption property for
all fields which source
expressions is not a table
field.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0222 SIFT index should not be Design Warning


used on primary or unique
key.

AA0223 The value of the Localizability Warning


OptionCaption property of
Fields must be filled in.

AA0224 The count of option Localizability Warning


captions specified in the
OptionCaption property is
wrong.

AA0225 You must specify a caption Localizability Warning


in the Caption property for
Fields that exist on page
objects.

AA0226 The value of the Caption Localizability Warning


property of Fields must be
filled in.

AA0227 Optional return value Design Warning


should not be omitted in
upgrade codeunits.

AA0228 The local method must be Design Warning


used; otherwise removed.

AA0230 Version should not be Design Warning


specified for internal
assemblies.

AA0231 StrSubstNo or string Design Warning


concatenation must not be
used as a parameter in the
Error method.

AA0232 The FlowField of a table Design Info


should be indexed.

AA0233 Use Get(), FindFirst() and Design Warning


FindLast() without Next()
method.

AA0235 When using Design Info


'OnInstallAppPerCompany'
you should also add
'Company-
Initialize'::'OnCompanyInitial
ize' event subscriber.

AA0237 The name of non- Readability Warning


temporary variables must
not be prefixed with Temp.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0240 Email and Phone No must Design Warning


not be present in any part
of the source code.

AA0241 Use all lowercase letters for Readability Hidden


reserved language
keywords.

AA0242 Limit JIT loads by selecting Design Warning


all fields for load.

AA0243 Running an upgrade Design Warning


codeunit is not allowed.

AA0244 Do not use identical names Design Warning


for parameters and global
variables.

AA0245 To avoid confusion, do not Design Warning


give parameters the same
name as fields, methods, or
actions in the same scope.

AA0448 You must use the Localizability Warning


FieldCaption method
instead of the FieldName
method and TableCaption
method instead of
TableName method.

AA0470 Placeholders should have a Localizability Warning


comment explaining their
content.

See Also
Using the Code Analysis Tool
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools with the Ruleset
PerTenantExtensionCop Analyzer Rules
2/6/2023 • 2 minutes to read • Edit Online

PerTenantExtensionCop is an analyzer that enforces rules that must be respected by extensions meant to be
installed for individual tenants.

Rules
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

PTE0001 Object ID must be in free Extensibility Error


range.

PTE0002 Field ID must be in free Extensibility Error


range.

PTE0003 Procedures must not Extensibility Error


subscribe to CompanyOpen
events

PTE0004 Table definitions must have Configuration Error


a matching permission set.

PTE0005 The compilation target of Extensibility Error


an application must be a
value that is allowed in a
multi-tenant SaaS
environment

PTE0006 Encryption key functions Extensibility Error


must not be invoked.

PTE0007 Test assertion functions are Extensibility Error


not allowed in a non-test
context.

PTE0008 Page controls and actions Extensibility Error


must use the
ApplicationArea property

PTE0009 This app.json property must Extensibility Error


not be used for per-tenant
extensions.

PTE0010 The extension name is too Extensibility Error


long.

PTE0011 The publisher name is too Extensibility Error


long.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

PTE0012 InternalsVisibleTo should Extensibility Warning


not be used as a security
feature.

PTE0013 Entitlements cannot be Configuration Error


defined in an extension.

PTE0014 Permission Sets should not Configuration Warning


be defined in XML files.

PTE0015 The extension name is not Extensibility Error


valid.

See Also
Using the Code Analysis Tool
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools with the Ruleset
UICop Analyzer Rules
2/6/2023 • 2 minutes to read • Edit Online

UICop is an analyzer that enforces rules that must be respected by extensions meant to customize the Web
Client.

Rules
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AW0001 The Web client does not WebClient Warning


support displaying the
Request page of XMLPorts.

AW0002 The Web client does not WebClient Warning


support displaying both
Actions and Fields in Cue
Groups. Only Fields will be
displayed.

AW0003 The Web client does not WebClient Warning


support displaying Repeater
controls containing Parts.

AW0004 A Blob cannot be used as a WebClient Warning


source expression for a
page field.

AW0005 Actions should use the WebClient Info


Image property.

AW0006 Pages and reports should WebClient Info


use the UsageCategory and
ApplicationArea properties
to be searchable.

AW0007 The Web client does not WebClient Error


support displaying Repeater
controls that contain
FlowFilter fields.

AW0008 The Web client only WebClient Warning


supports displaying
Repeater controls in pages
of type List, ListPart, and
Worksheet.

AW0009 Using a Blob with subtype WebClient Warning


Bitmap on a page field is
deprecated. Instead use the
Media/MediaSet data types.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AW0010 A Repeater control used on WebClient Warning


a List page must be defined
at the beginning of the
area(Content) section.

AW0011 Add PromotedOnly="true" WebClient Info


to some or all promoted
actions to avoid identical
actions from appearing in
both the promoted and
default sections of the
command bar.

AW0012 The Web client does not WebClient Warning


support properties for
teaching tips in certain
contexts.

AW0013 Groups containing WebClient Warning


promoted actions should
not be hidden.

AW0014 Groups containing WebClient Warning


ActionRef targets should
not be hidden.

AW0015 Actions with scope repeater WebClient Warning


must be promoted.

See Also
Using the Code Analysis Tool
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools with the Ruleset
Compilation Scope Overview
2/6/2023 • 2 minutes to read • Edit Online

In Dynamics 365 Business Central, there are different layers to manage what can be published to the server and
accessed from within a project.

Configure extension target on the server


By setting the Allowed Extension Target Level flag in the server configuration, you control what can be
published to the server by setting the Cloud or OnPrem flag. For more information, see Configuring Business
Central Server.

Configure extension target for an extension


In the manifest of an extension (the app.json file), you can set the target property to specify the compilation
target of an extension. The available values are Internal , Extension , OnPrem , and Cloud .

IMPORTANT
The Internal and Extension values have been deprecated, starting with runtime 4.0 and replaced by the OnPrem
and Cloud respectively.

The target property informs the compiler which APIs can be used within the current project.
If you specify "target":"OnPrem" , you can use any platform APIs and .NET types. This is the most permissive
target. It's only if you specify this target, that you can use methods marked with Scope('OnPrem') or tables
with the property Scope (Tables) set to OnPrem .
If you specify "target":"Cloud" , you can only use APIs that are safe for use in a cloud environment. If the
target is set to Cloud , the extension can't use any method marked with Scope('OnPrem') or table with the
property Scope set to the OnPrem . For example, if you have two extensions; A and B. Extension A has an
app.json target setting "target": "OnPrem" and defines a method with the Scope Attribute set to
[Scope('OnPrem')] . Extension B has a dependency on extension A and extension B has an app.json target
setting "target": "Cloud" and tries to call the method in extension A marked with scope OnPrem , you'll get a
compile error when you're trying to compile extension B. For more information, see JSON Files.

NOTE
A table with the property Scope set to OnPrem carries this scope forward to every other object that might refer it as
SourceTable , even if those elements are declared within the same extension.

Methods and tables scope


Methods can be marked with the [Scope()] attribute to specify the compilation target and tables can be
marked with the Scope property. Both instruct the compiler, which targets the method or table can be used in.
For more information, see Scope Attribute and Scope (Table) Property.

See Also
AL Development Environment
Developing Extensions in AL
JSON Files
Scope Attribute
Scope (Table) Property
Configuring Business Central Server
Debugging in AL
2/6/2023 • 7 minutes to read • Edit Online

Debugging is the process of finding and correcting errors. With Visual Studio Code and the AL Language
extension, you get an integrated debugger to help you inspect your code and verify that your application can
run as expected. You can start a debugging session by pressing F5 . For more information about Debugging in
Visual Studio Code, see Debugging.
An alternative to classic debugging is snapshot debugging, which allows you to record running code, and later
debug it. For more information, see Snapshot Debugging.

IMPORTANT
To enable debugging in versions before Business Central April 2019, the NetFx40_LegacySecurityPolicy setting in the
Microsoft.Dynamics.Nav.Server.exe.config file must be set to false . This step requires a server restart.

IMPORTANT
To use the development environment and debugger, you must make sure that port 7049 is available.

There are some limitations to be aware of:


"External code" can only be debugged if the code has the allowDebugging flag set to true . For more
information, see Resource Exposure Policy Setting.
The debugger launches a new client instance each time you press F5 . If you close the debugging session and
then start a new session, this new session will rely on a new client instance. We recommend that you close
the Web client instances when you close a debugging session.
Pausing the debugging session isn't supported.
To control table data synchronization between each debugging session, see Retaining table data after publishing.

TIP
To be able to debug an online environment with an Embed app published in it, make sure to specify the
applicationFamily parameter in your launch.json file. You must define the application family for your Embed app
during onboarding.

Breakpoints
The basic concept in debugging is the breakpoint, which is a mark that you set on a statement. When the
program flow reaches the breakpoint, the debugger stops execution until you instruct it to continue. Without
any breakpoints, the code runs without interruption when the debugger is active. You can set a breakpoint by
using the Debug Menu in Visual Studio Code. For more information, see Debugging Shortcuts.
Set breakpoints on the external code that isn't part of your original project. You can step into the base
application code by using the Go to Definition feature and set breakpoints on the referenced code, which is
generally a .dal file. To set a breakpoint on the external code or base application code, you do as follows:
Use Go to Definition , which opens the "external file", and then a breakpoint can be set.
By using the debugger, you can step into the code, and then set a breakpoint.
The following video illustrates that Customer.dal is an external file. A breakpoint is set in the Customer.dal file,
which is referenced from your AL project to stop execution at the marked point.

For more information about Go to Definition , see AL Code Navigation.

Break on errors
Specify if the debugger breaks on the next error by using the breakOnError property. If the debugger is set to
breakOnError , it stops execution on both errors that are handled in code and unhandled errors.

The default value of the breakOnError property is true , which means the debugger stops the execution that
throws an error by default. To skip the error handling process, set the breakOnError property to false in the
launch.json file.

TIP
If the debugging session takes longer, you can refresh the session by pressing the Ctrl+Shift+P keys and selecting
Reload Window .

Break on record changes


Specify if the debugger breaks on record changes by using the breakOnRecordWrite property. If the debugger is
set to break on record changes, then it breaks before creating, modifying, or deleting a record. The following
table shows each record change and the AL methods that cause each change.

REC O RD C H A N GE A L M ET H O DS

Create a new record Insert Method (Record)

Update an existing record Modify Method (Record), ModifyAll Method (Record),


Rename Method (Record)

Delete an existing record Delete Method (Record), DeleteAll Method (Record)


The default value of the breakOnRecordWrite property is false , which means that the debugger isn't set to break
on record changes by default. To break on record changes, you can set the breakOnRecordWrite property to true
in the launch.json file. For more information, see JSON Files.

Debugging large size variable values


Variables with values larger than 1024 bytes are truncated ( … ) and can't be fully inspected from the
VARIABLES window. To inspect a large size variable value, instead use the DEBUG CONSOLE and write the
name, or qualified name of a variable to inspect at the prompt and then press Enter .

Attach and Debug Next


If you don't want to publish and invoke the functionality to debug it, you can attach a session to a specified
server and await a process to trigger the breakpoint you have set. For more information, see Attach and Debug
Next.

Debugging shortcuts
K EY ST RO K E A C T IO N

F5 Start debugging

Ctrl+F5 Start without debugging

Shift+F5 Stop debugging

Ctrl+Shift+F5 Start debugging without publishing.


Using this command on a changed but unpublished code
may trigger false existing breakpoints. For example, if you
modify the method "foo", add two lines, put a breakpoint on
the second line, and then start debugging without
publishing, that breakpoint won't be hit, or if it's hit isn't your
new code that it breaks. If it breaks, it will break on the line
that the server thinks the breakpoint is, based on the last
published code.

Alt+F5 Start RAD with debugging. For more information, see


Working with Rapid Application Development.

F10 Step over

F11 Step into

Shift+F11 Step out

F12 Go To Definition

For more shortcuts, see Debugging in Visual Studio Code. For working with Snapshot Debugging, see Snapshot
Debugging.

Debugging SQL behavior


Traditionally, debugging AL has been about examining the behavior of the language runtime, for example,
looking into the content of local variables at a breakpoint. As of Business Central April 2019, the AL debugger
also offers the capability to examine your AL code's effect on the Business Central database. The
enableSQLInformationDebugger setting enables this functionality. For more information, see JSON Files.

View database statistics


In the VARIABLES pane in debugger, expand the <Database statistics> node to get insights such as the
current network latency between the Business Central Server and the Business Central database, the total
number of SQL statements executed, the total number of rows read, and locks held, as well as insights into the
most recent SQL statements executed by the server. The following insights are part of the database statistics:

IN SIGH T DESC RIP T IO N

Current SQL latency (ms) When the debugger hits a breakpoint, the Business Central
Server will send a short SQL statement to the database, and
measures the time it takes. The value is in milliseconds.

Number of SQL Executes This number shows the total number of SQL statements
executed in the debugging session since the debugger was
started.

Number of SQL Rows Read This number shows the total number of rows read from the
Business Central database in the debugging session since
the debugger was started.

TIP
You can also get database insights from the AL runtime by using the SqlStatementsExecuted() and SqlRowsRead()
methods.

View locks held


The Locks part of the database statistics shows an overview of the SQL locks held by the debugged session. The
insight can be used to understand the locks acquired while stepping through AL code. The access mode of the
lock is also provided, which allows advanced developers to establish concurrency compatibility with other
operations.
View SQL statement statistics
The database insights also let you peek into the most recent and the latest long running SQL statements
executed by the server. To view a list of the statements, expand either the <Last Executed SQL Statements>
or <Last Long Running SQL Statements> node. The following insights are part of the SQL statement
statistics:

IN SIGH T DESC RIP T IO N

Statement The SQL statement that the AL server sent to the Business
Central database. For further analysis, you can copy the SQL
statement into other database tools, such as SQL Server
Management Studio.

Execution time (UTC) The timestamp (in UTC) of when the SQL statement was
executed. You can use this to infer whether the SQL
statement was part of the AL code between the current and
last breakpoint (if set).
IN SIGH T DESC RIP T IO N

Duration (ms) The duration in milliseconds of the total execution time of


the SQL statement measured inside the Business Central
Server. You can use Duration (ms) to analyze whether you're
missing indexes (Business Central keys), or to experiment
with database partitioning and/or compression performance.

Approx. Rows Read This number shows the approximate number of rows read
from the Business Central database by the SQL statement.
You can use this insight to analyze whether you're missing
filters.

The number of SQL statements tracked by the debugger can be configured in the Business Central Server. The
default value is 10.

NOTE
For Business Central on-premises, the Business Central Server instance has several configuration settings that control the
SQL statistics. These statistics are gathered and then displayed in the debugger, like whether long running SQL
statements or SQL statements are shown. Check the server configuration if you don't see the insights that you expect in
the debugger. For more information, see Configuring Business Central Server.

NonDebuggable attribute
The ability to debug certain methods and/or variables can be restricted. For more information, see
NonDebuggable Attribute.

Authenticate with Azure AD on Business Central on-premises


You can use Azure AD as the authentication mechanism for Business Central on-premises or containers. For
more information, see Azure AD authentication for Business Central on-premises.

See Also
Attach and Debug Next
Developing Extensions
JSON Files
AL Code Navigation
Attach and Debug Next
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

If you don't want to publish and invoke functionality to debug it, you can instead attach a session to a specified
server, and await a process to trigger the breakpoint you've set. Then debugging starts when the code that the
breakpoint is set on is hit.

NOTE
To use the attach functionality, you must make sure that your app is published with Ctrl+F5 first, or with Alt+Ctrl+F5
for RAD publishing, before you start the debugging session with F5 . To debug using attach, you must make sure to
debug on a new session. Creating a new server session from the client can be achieved for example by launching a new
client session. Pressing F5 (Refresh) in a browser may not create a new server session, because it is cached, but if a session
is expired and refreshed that will create a new session.

IMPORTANT
Only the user who starts a Visual Studio Code attach session can issue the Web request on the server.

Attach configuration
You can activate the attach functionality by creating a new configuration in the launch.json file. The
configuration has two flavors; Attach to the next client on the cloud sandbox and Attach to the next
client on your ser ver . Use the first option to attach to a cloud session, and the second option to attach to a
local server.
In the attach configuration, the breakOnNext setting specifies the next client to break on when the debugging
session starts and allows only one option. The available options are: WebServiceClient , WebClient , and
Background . The example below illustrates a configuration for a local server.

...
{
"name": "My attach to local server",
"type": "al",
"request": "attach",
"server": "https://localhost",
"serverInstance": "BC200",
"authentication": "Windows",
"breakOnError": true,
"breakOnRecordWrite": false,
"enableSqlInformationDebugger": true,
"enableLongRunningSqlStatements": true,
"longRunningSqlStatementsThreshold": 500,
"numberOfSqlStatements": 10,
"breakOnNext": "WebClient"
}
...
Attach support
The following configurations for attach are supported:

B USIN ESS C EN T RA L W EB C L IEN T W EB SERVIC E C L IEN T B A C KGRO UN D SESSIO N

On-premises Supported Supported Supported

Sandbox Not supported Supported Not supported

To start an attach session


1. In Visual Studio Code, under Run , choose Add configuration .
2. Choose whether to attach to a cloud or a local session.
The launch.json file is now populated with the correct attach configuration settings. If you've selected a local
session, change the default settings to point to your local server in the server and serverInstance settings.
3. Set breakOnNext to specify the client type on which to break.
4. In your code, set at least one breakpoint using Run from the toolbar, choose New breakpoint , and then
choose which type of breakpoint to add. You can always add more breakpoints while debugging.
5. If your most recent app is not yet published, it's important to make sure you publish it pressing Ctrl+F5 ,
alternatively Alt+Ctrl+F5 for RAD publishing. Then, use F5 to start the attach session.

IMPORTANT
If you modify the app code during the debugging session, make sure to re-publish the app using Ctrl+F5 .

6. After publishing the app, press F5 to start a debugging session.

NOTE
If you have more attach configuration settings, you must first select which configuration to start.

7. Debug and inspect the code. You can add more breakpoints while debugging.
8. Stop the attach debugging session by selecting Detach in the Visual Studio Code toolbar.

See Also
AL Development Environment
Developing Extensions in AL
Debugging
Snapshot Debugging
JSON Files
EnableLongRunningSQLStatements Property
EnableSQLInformationDebugger Property
LongrunningSQLStatementsThreshold Property
NumberOfSQLStatements Property
Snapshot Debugging
2/6/2023 • 10 minutes to read • Edit Online

NOTE
With Business Central 17.2 - Snapshot Debugging is available in production cloud environments.

With snapshot debugging, you can record AL code that runs on the server, and when it has completed, debug
the recorded snapshot in Visual Studio Code. Snapshot debugging lets you inspect code execution and variables
in the production environment on a cloud service for a specified user session. To create and download a
snapshot file that exists on the server on behalf of an end-user, the user must be part of the D365 Snapshot
Debug permission set. For more information, see Assign Permissions to Users and Groups.
Snapshot debugging introduces the concept of snappoints. A snappoint is a breakpoint in Visual Studio Code
that is set while creating a snapshot but they don't stop execution of code like regular debugging. Snappoints
log the state at the breakpoint for later offline inspection. Snapshot debugging will record AL code as it runs on
the server, but will only collect variable information on:
Snappoints
AL exceptions

NOTE
With Business Central version 18.1, it's possible to snapshot the debug event subscribers triggered by built-in codeunit
triggers if a snappoint is placed in an AL file on the stack trace that leads to the built-in method. For more information,
see Snapshot debugging built-in methods.

IMPORTANT
To enable snapshot debugging, it's very important that the symbols on the tenant match the symbols on the server. This
isn't automatically detected, and must be manually checked. In this release, you can ensure this by copying the specific
sandbox and download symbols from that copy. Furthermore, any code that snappoints are set in, must have been
deployed, otherwise debugging will not work. For more information, see the section Downloading symbols on the
snapshot debugger endpoint.

Snapshot debugging keyboard shortcuts


In the following sections, you can read more about how to initialize, view the status, and finalize a snapshot
debugging session. It's useful to familiarize yourself with the following keyboard shortcuts. For more keyboard
shortcuts, see Keyboard Shortcuts.

K EY B O A RD SH O RTC UT A C T IO N

F7 Start a snapshot debugging session

Shift+F7 List all available snapshots

Alt+F7 Finish a snapshot debugging session


Initialize a snapshot debugging session
You can start a snapshot by creating a snapshot configuration file in Visual Studio Code. There are two template
configurations for a snapshot, which are accessed by selecting Add Configuration in Visual Studio Code.
AL: Initialize a snapshot debugging session locally
AL: Initialize a snapshot debugging session on cloud
Choose whether to run the session on a cloud service or locally. The configuration file contains the following
information:

SET T IN G DESC RIP T IO N

userId The GUID of the user who initiated the process to start
snapshot debugging. For on-premises, this can also be the
user name in user password authentication scenarios. The
user must be able to start, or have a session type opened
that is specified in the breakOnNext parameter.
Note: Specifying userId doesn't work with Windows
authentication: "authentication" : "Windows" , in which
case you can only choose sessionId or attach to the next
session. For more information, see JSON Files.

sessionId A session ID for the user specified in userId .

snapshotVerbosity Determines how much execution context to be recorded. If


SnapPoint is specified, then only methods that hit a
snappoint will be recorded.

tenant The AAD tenant ID for the tenant to connect to. Specify this
if your target is a different tenant from the user's own AAD
tenant, for example when running as a delegated admin.

When a configuration is defined, a snapshot debugging session can be initialized by pressing Ctrl+Shift+P ,
and then selecting AL:Initialize Snapshot Debugging or by pressing F7 .

NOTE
If you're going to use the snapshot for profiling the code, you must enable the configuration parameter called
executionContext . For more information, see AL Profiler Overview.

To record the AL execution, the server will now wait for a connection to happen where the following rules apply:
If a sessionId is specified for a userId in the given tenant, then it will be the session that's going to be
snapshot debugged.
If only a userId is specified for a given tenant then the next session that is specified in the breakOnNext
configuration parameter is snapshot debugged.
If no userId is specified then the next session on a given tenant that validates the breakOnNext parameter
will be snapshot debugged.

TIP
If you're having difficulty getting the snapshot debugger to attach to a new session using WebClient for the
breakOnNext configuration parameter, then close the browser window and try again.
TIP
To do snapshot debugging of Service to Service (S2S) web service calls set the breakOnNext configuration parameter to
WebServiceClient in the launch.json file and use table explorer to find the userId of the user record mapped to
the S2S Azure AD Authentication Application. When the snapshot session is initialized, trigger the session either from the
integration (service or device) or manually by invoking a web service call using tools like Postman or Fiddler. For
information about creating S2S refer to Using Service to Service Authentication, Client Credentials Grant Flow, App-only
Authentication, and Postman HowTo.

Once a snapshot debugging session is initialized, the snapshot debugging session counter on the status bar will
be updated and look like this:

Status of a snapshot debugging session


Clicking on the status bar icon or pressing Shift+F7 will bring up a list of all available snapshots.
The status list will show the state of a snapshot-debugged session.
A snapshot debugging session can be in one of the three states:
Initialized - A request is issued and the server is waiting for the next session to be snapshot debugged
based on the above rules.
Star ted - You've attached to an end-user session to snapshot debug.
Finished - When the snapshot debugging session has finished.
Downloaded - When the snapshot file is downloaded.

Stop a snapshot debugging session


You can stop a snapshot debugging session by pressing Alt+F7 . This brings up all snapshot sessions that have
been started. Choosing one will close the session debugging on the server and download the snapshot file.

IMPORTANT
The snapshot file can contain customer privacy data and must therefore be handled according to the privacy and
compliance policies. The file should be deleted when it's not needed anymore.

Snapshot debugging sessions that have produced a snapshot file can be debugged. The location of a snapshot
file is controlled by the al.snapshotOutputPath configuration parameter. By default it's local to the current
workspace and it's called ./.snapshots . For more information, see AL Language Extension Configuration.

Download symbols on the snapshot debugger endpoint


In order to download symbols on a production server, you need permission related entries. The read-only access
to the Published Application table emphasized in the D365 Snapshot Debug permission set should be
granted.
Symbols download is using the snapshotInitialize debug configuration settings in Visual Studio Code, which is
set up when you choose either AL: Initialize a snapshot debugging session locally or AL: Initialize a
snapshot debugging session on cloud .
{
"name": "snapshotInitialize: MyServer",
"type": "al",
"request": "snapshotInitialize",
"environmentType": "OnPrem",
"server": "http://localhost",
"serverInstance": "BC190",
"authentication": "UserPassword",
"breakOnNext": "WebClient"
},

IMPORTANT
Debugging requires that symbols on the server are matched with the symbols that the user has locally. If this isn't the
case, and you set a breakpoint on a given line in Visual Studio Code, the line of the code may differ from what is on the
server. For example, if you don't download the symbols from the production servers for snapshot debugging, you can face
a scenario where you set a breakpoint in a DAL file on line 12, but line 12 on the server is an empty line or a completely
different line because the symbols aren't the same.

Debugging a snapshot file


There are two user actions that will start snapshot debugging:
Creating a new launch debug configuration and specifying the snapshot file name in the snapshotFileName
configuration setting. This is the only setting that is needed besides the type, request, and name.
Choosing the status icon or by pressing Shift+F7 and selecting a finished snapshot-debugged session.
Once a snapshot debugging session starts in Visual Studio Code, code execution will stop at the first snappoint.
AL exceptions will be treated as snappoints, with the only difference that they can't be removed by the user
actions. Other snappoints are regular breakpoints that can be removed or readded by the user actions. If no
snappoints are specified in the first recorded methods; the first line is the entry breakpoint.
The user can set breakpoints and continue execution to these breakpoints for testing because a snappoint is
what carries the real information, so a line can be hit.
Viewing executed code
APPLIES TO: Business Central 2022 release wave 2 and later

During snapshot debugging playback, the left-side code editor gutter contains a vertical visual bar to indicate
which code was executed in the snapshot capture. The color of the gutter bar can be controlled using the
al.snapshotDebuggerLinesHitDecoration in the settings.json file. For more information, see AL Language
Extension Configuration.

Snapshot debugging the built-in codeunit triggers


Built-in codeunit triggers can be snapshot-debugged if they're part of the stack trace, these are System Action
Triggers, or Company Triggers. This provides a way to snapshot debug that part of the Base App too. To help
locate where built-in codeunit triggers are called, use the Event Recorder in Business Central. From the code,
when all symbols on the snapshot endpoint have been downloaded, see Downloading symbols on the snapshot
debugger endpoint, you can add AL code that contains a reference to that particular event subscription and then
use Go to Definition to locate the place where that particular codeunit trigger is defined in the .dal file. Adding
a snappoint to the code in the .dal file and then initiating the snapshot debugger session will ensure that the
code is part of the stacktrace. When the generated snapshot file is then opened in the debugger, the execution
will break on the snappoint.
Snapshot debugging versus regular debugging
Snapshot debugging is almost the same as a regular debugging with the differences mentioned below:

SN A P SH OT VERSUS REGUL A R DEB UGGIN G

Breakpoints can be added or removed and they'll be hit if the breakpoint is in the execution context of a recorded state. This
means that if you walk the execution stack for a breakpoint and the next stepped line is reached, then the code will break on
the breakpoint.

A snappoint is a breakpoint in Visual Studio Code that is set when creating a snapshot. They don't, however, stop execution of
code like when using regular debugging. Snappoints instruct execution to log the state at the breakpoint for later offline
inspection.

You can always navigate through all the breakpoints with Continue (F5). The order may not be the same as the execution
order on the Business Central server. This is because some calls on the server are AL calls with non-walkable stacks. Some are
direct server calls on the server like triggers. A snapshot debugging session on the Business Central server can only record AL
calls and walk AL stack traces.

This is also true when stepping. The rule of thumb is that breakpoints within the reach are hit first, and if there are none; the
next line is hit. Breakpoints on triggers may not always qualify as code within reach.

Variable data is only shown on snappoints.

If there are no frames available, snapshot debugging will stop.

Stepping out of triggers with no recorded stack information will move execution to the first recorded method's first line. This
may be far from the user's execution of interest. For example, stepping out from an OnOpenPage trigger with a snappoint
may land on deep inside base code execution where recording has started. Navigating with F5 will start over breakpoint
resolution, thus this is an exit strategy from a scenario like this.

A snappoint may resolve as a non-reachable breakpoint if there was no execution state on the server hitting the snappoint.

A snapshot debugger session with a Business Central server will be closed if not attached to after 30 minutes.

If a snapshot debugger session is started, it has to be finished after 10 minutes.

See Also
Debugging
Attach and Debug Next
Developing Extensions
JSON Files
AL Code Navigation
EnableLongRunningSQLStatements Property
EnableSQLInformationDebugger Property
LongrunningSQLStatementsThreshold Property
NumberOfSQLStatements Property
Debug Upgrade and Install Code
2/6/2023 • 2 minutes to read • Edit Online

To test and troubleshoot issues in install and upgrade code, it's important to ensure that these processes run
smoothly when the app is installed for the first time or when it's upgraded. You can add breakpoints in the install
or upgrade code, and then attach and trigger publishing of an extension to debug these scenarios.

Attach and debug


1. In Visual Studio Code, ensure that you've a launch.json file with the request option set to attach . For
more information, see Attach and Debug Next.
2. Add one or more breakpoints in the code that you want to debug. For more information, see Debugging.

NOTE
If you don't increment the version of the app, the install codeunits will not be invoked. If you do increment the
version of the app, or if you set the forceUpgrade flag to true in the launch.json file, the upgrade
codeunits will be invoked.

3. If your app isn't yet published, then use Ctrl+F5 to publish the app file first; the attach option won't publish
the app. After, start the attach session as you would normally start the debugging session with F5 .

See Also
Debugging
Snapshot Debugging
Attach and Debug Next
AL Profiler Overview
2/6/2023 • 8 minutes to read • Edit Online

> INTRODUCED IN: Business Central 2021 release wave 2 and updated with sampling profiling for Business
Central 2022 release wave 1.
Profiling allows you to collect data about performance and analyze this data with the goal of optimizing a
certain area in the code or a certain process. The AL Profiler for the AL Language extension offers options for
instrumentation profiling and sampling profiling.

Snapshot of the running code


With the AL Profiler for the AL Language extension, you can capture a performance profile of the code that was
executed for a snapshot. There are two types of profiling; instrumentation profiling and sampling profiling. Both
types of profiling are based on a snapshot of running code. The instrumentation profiling is more accurate and
provides more insight. Using the performance profiling editor view in Visual Studio Code, you can investigate
the time spent on execution, using top-down and bottom-up call stack views. The sampling profiling is less
accurate, but can provide faster insights into performance trends on code.

Snapshot configuration settings


In order to do any profiling on code, first, you must capture a snapshot of running code. Before doing that, you
must set up a snapshot configuration in the launch.json file. The configuration settings depend on what type of
profiling you want to perform.
To set up a snapshot configuration for instrumentation profiling
The parameter called executionContext has the following values in the table below. If nothing is specified, the
configuration is DebugAndProfile by default.

O P T IO N DESC RIP T IO N

Debug The snapshot session won't gather profile information.

Profile The snapshot session will only gather profile information,


snappoints will be ignored, and debugging won't work.

DebugAndProfile Both debugging and profiling will be available as a result of a


snapshot session. This is the default setting.

The profilingType must be set to Instrumentation as illustrated in the example below.


Looking at the example, if we want to use the snapshot both for debugging and profiling purposes, the
configuration for the snapshot in the launch.json file must look equivalent to the following example file:
"configurations": [
{
"name": "snapshotInitialize: Your own server",
"type": "al",
"userId": "555",
"request": "snapshotInitialize",
"environmentType": "OnPrem",
"server": "http://localserver",
"serverInstance": "BC200",
"authentication": "Windows",
"breakOnNext": "WebClient",
"executionContext": "DebugAndProfile",
"profilingType": "Instrumentation"
}

To set up a snapshot configuration for sampling profiling


For sampling profiling, choose Sampling as the profilingType in the launch.json configuration file. The
executionContext property must be set to Profile . Debugging isn't supported while running sampling
profiling. Finally, the profilingType must be set to Sampling as shown in the example below.

"configurations": [
{
"name": "Your own server",
"type": "al",
"userId": "555",
"request": "snapshotInitialize",
"environmentType": "OnPrem",
"server": "http://localserver",
"serverInstance": "BC200",
"authentication": "Windows",
"breakOnNext": "WebClient",
"executionContext": "Profile",
"profilingType": "Sampling"
}

Generating a profile file for instrumentation profiling


Once the snapshot file is downloaded, you can generate a profile file. This can be done in one of the two ways:
1. Open the Command Palette by using the Ctrl+Shift+P shortcut, then select the AL: Generate profile file
command and choose a snapshot from the dropdown menu.
2. Alternatively, in the Visual Studio Code explorer, right-click the specific snapshot file and choose Generate
Profile File .
The profile file for AL code has the extension .alcpuprofile and when you open the file, it displays in the
performance profiling editor view in the Visual Studio Code.
Graph of method calls
To investigate the graph of method calls, open the generated profile file in the performance profiling editor. If
you select the file directly, it opens up in top-down view. For more information, see the View modes section.
You can also right-click a profile file and get the following options: AL Profile Visualizer TopDown Graph
and AL Profile Visualizer BottomUp Graph . When the profile file opens, it looks similar to the illustration
below:
To investigate the data shown in the graph, you can use different view modes as described in the next section.
Choose a specific method to navigate to the code. The (default) color legend of the graph is as follows:

L AY ER C O LO R

System Application Green

Base Application Magenta

Other Extensions Yellow

System Blue

Custom Named extension, defaults to "extension" if not found

The color legend can be changed by specifying the al.profilerColors property in the AL configuration. For
more information, see AL Language Extension Configuration.

IMPORTANT
If you run Visual Studio Code with the setting Run as administrator , the graph will not display in the performance
profiling editor view. As a workaround, you can launch Visual Studio Code from the command line with the flag
--no-sandbox .

View modes
To switch between views, you can either right-click the profile file and choose a view, or you can use the small
button in the upper right corner. There are two different view modes in the graph; top-down and bottom-up.
When sorting the stack in top-down direction, the graph sorts the methods according to the call sequence,
which means that the child nodes are the methods called from the parent node. And when sorting bottom-up,
the graph is sorted as a reverse call stack, which means that the child nodes are methods who called the parent
node.
Details
To investigate further, the Self-time and Total time columns are important indicators of where time is spent in
the code. The Self-time is the amount of time spent in the method only, excluding any calls out of the method.
The Total time is the amount of Self-time plus any calls out of the method. On bottom-up graphs the Total
time and Self-time columns are sortable. Clicking them will first sort them in ascending order, clicking again
will sort them in descending.
Hit count is only available on top-down graphs and shows the number of times a specific method was called.
Time spent is aggregated.
Filter
The nodes in the graph can be filtered. The syntax is as follows:
@column name | <alias> <op> <value> where
<column name> := [function, url, path, selfTime, totalTime, id, objectType, objectName, declaringApplication]

C o l u m n n a m e a l i a se s

The aliases that are available for the column names are:
<alias> := [f, u, p, s, t, id, ot, on, da]
<op> := [numeric operators, boolean operators, string operators]
numeric operators : [:, =, >, <, <=, >=, <>, !=]
: := equal
boolean operators : [:, =, <>, !=]
string operators : [:, =, !=, <>, ~, =]
~ = := <regex>
F i l t e r e x a mp l e s

EXP RESSIO N RESULT

@t > 1000 Shows all nodes in the graph where the total time is greater
than 1 second.

@h > 20 Shows all nodes in the graph where the hit count was larger
than 20.

@da ~= Ba* Shows all nodes in the graph that start with Ba.

Keyboard shortcuts for navigating the graph


The following table provides an overview of the shortcut key combinations that you can use when you're
working in the graph of method calls.

K EY B O A RD SH O RTC UT A C T IO N

Enter+Toggle Expand and collapse a node.

Arrow+Left Collapse a node.

Arrow+Right Expand a node.

-(minus) Collapse all nodes.

*(star) Expand one level for all nodes. Consecutive keystrokes will
expand to the next level.

Inline Profiler CodeLens for AL profiling results


The Profiler CodeLens for AL shows profile results. At hover, the Profiler CodeLens displays time spent in
milliseconds for a specific method, and the number of hits on the method. When opening a profiler file, the lens
will show information on all statements that appear as frames in the profiler.
General CodeLens support for the Visual Studio Code is enabled in the user or workspace settings by adding the
"editor.codeLens": true setting for the specific user or for the workspace. To activate this setting, press
Ctrl+Shift+P , and then choose Preferences: Open Settings (UI) for workspace settings, or choose
Preferences: Open User Settings for user settings.
While in the settings file, you can now add two options for the Profiler CodeLens for AL. The
"al.areProfileLensesSupported": true enables the CodeLens and is by default true. The option for adding a
lower limit for time spent on statement execution is al.statementLensMin . This must be set to the value in
milliseconds, which is the lower limit. The default for this setting is 500 milliseconds (ms). Any value below the
stated threshold won't be shown. For more information, see AL Language Extension Configuration.

NOTE
Because of the aggregation of frames, there can be minor discrepancies between the information appearing in the
CodeLens and in the profiler.

Sampling profiling
Sampling profiling is useful as an initial analysis of code performance. You can perform sampling profiling in
Visual Studio Code on AL code. Sampling profiling is based on a snapshot of running code. It gets the AL stack
frame of the currently executing AL method in the context of an attached session in a given time interval.
Sampling isn't as accurate as instrumentation profiling is. But it can give an indication about the self-time of an
AL method. The benefit of doing sampling profiling is that it's less noisy and is much faster to get profile
information.
There are a few server restrictions for sampling profiling to be aware of:
The maximum duration of a sampling session is 10 minutes. This is a configurable server setting.
The number of stack frame entries is limited to 2000. This is a configurable server setting.
Performance profiling in Business Central
In Business Central, you can use the Performance Profiler page to record a snapshot to do sampling profiling.
This allows for recording of a process that seems slow directly in Business Central. When the Performance
Profiler has run and recorded a process in Business Central, it generates a .alcpuprofile file, which can be
downloaded and shared using OneDrive. When receiving such a .alcpuprofile file, it can be opened in the
Visual Studio Code and further investigated. For more information, see Performance Profiler Overview.

See Also
Snapshot Debugging
AL Language Extension Configuration
Performance Profiler Overview
Work with Rapid Application Development
2/6/2023 • 2 minutes to read • Edit Online

When working with Visual Studio Code and Dynamics 365 Business Central, you can benefit from Rapid
Application Development (RAD) on large code projects. RAD allows faster development on projects with a large
number of files by doing a delta compilation and publishing only on those application objects that have changed
during development in Visual Studio Code. RAD publishing is an interim state and doesn't replace a full publish.

How RAD works


The files that have been changed by the application developer within Visual Studio Code are persisted in a
special RAD (.rad) file during builds. This file is saved in the .vscode folder of the code project. RAD changes are
the changes of application objects within a RAD session. Only application objects, page customization objects,
and profile objects are handled for RAD. RAD changes won't be persisted during save, only during build, publish,
and debug.

IMPORTANT
The rad.json file should not be modified.

IMPORTANT
If you change many files and close Visual Studio Code without a build (Ctrl+Shift+B ), publish (Ctrl+F5 , Ctrl+Shift+F5 )
or debug (F5 , Shift+F5 ), all the RAD changes will be lost. This means that if you, in the next Visual Studio Code session
perform a RAD publishing, it'll be done on the latest changes and not on the prior changes. This can lead to an
incomplete published package if it succeeds. It's therefore a best practice to do a regular publish. You can always check the
RAD file in the code project to see what application objects are going to be changed during publishing.

In scenarios when application IDs are renamed, or refactored it's also a best practice to first do a full publishing,
and then a RAD publishing for the consecutive changes. RAD doesn't check for application ID changes and ID
changes can occur in a wrongly published application.
A RAD published file won't contain the following files that are normally packaged during regular publishing:
Translation files
Permission files
Custom word and report rdl layout files
Table data
Web service definitions
These files will need to be regenerated with full publishing (Ctrl+F5 ). A RAD file will be deleted as a result of a
successful publishing.

NOTE
If RAD publishing fails, then you must do a full publishing before performing another RAD publishing. The final state of an
application must be built using full publishing, and never with RAD publishing.
NOTE
When building using RAD, all translations will be ignored, even though the "features": [ "TranslationFile" ]
setting is specified in the app.json file. For more information, see Working with Translation Files.

RAD shortcuts
There are two commands for starting a RAD-based action.

SH O RTC UT DESC RIP T IO N

Ctrl+Alt+F5 Start RAD publishing without debugging.

Alt+F5 Start RAD with debugging.

See also
Developing Extensions in AL
Debugging
Sign an APP Package File
2/6/2023 • 3 minutes to read • Edit Online

Code signing is a common practice for many applications. It's the process of digitally signing a file to verify the
author and that the file hasn't been tampered with since it was signed. The signature of the APP package file is
verified during the publishing of the extension using the Publish-NAVApp cmdlet. For more technical information
on signing, see Authenticode.

NOTE
If you want to publish an unsigned extension package in your on-premise environment, you need to explicitly state it by
using the - SkipVerification parameter on the Publish-NAVApp cmdlet. An extension without a valid signature won't be
published on AppSource.

The signing of an APP package file must be performed on a computer that has Dynamics 365 Business Central
installed. If you're running Dynamics 365 Business Central on Docker for your development environment, that
environment will meet this requirement. You must also have the certificate that will be used for signing on the
computer. The certificate must include code signing as the intended purpose. It's recommended that you use a
certificate purchased from a third-party certificate authority.

IMPORTANT
If you publish the extension as an app on AppSource, the APP package file must be signed using a certificate purchased
from a Certification Authority that has its root certificates in Microsoft Windows. You can obtain a certificate from a range
of certificate providers, including but not limited to DigiCert and Symantec, see the image below. You don't have to use an
EV Code Signing certificate, standard code signing certificates can be used for signing your extensions.

Steps for signing your .app file


1. Prepare your computer for signing.
2. Make sure that you sign the .app file on a computer that has Dynamics 365 Business Central installed.
3. Copy the certificate that you purchased from a third-party certificate authority to a folder on the computer.
The example uses a pfx version of the certificate. If the certificate you purchased isn't in a pfx format, create a
PFX file. The file path for the sample command is C:\Certificates\MyCert.pfx . (Optionally, create your own
certificate for local test or development purposes using the Self-signed certificate information).
4. Install a signing tool such as SignTool or SignCode to the computer. The sample command will use SignTool.
5. Copy your extensions .app file to the computer if it's not already on the computer. The file path for the sample
command is C:\NAV\Proseware.app .
6. Run the command to sign the .app file.
7. The following example signs the Proseware.app file with a time stamp using the certificate in the password-
protected MyCert.pfx file. The command is run on the computer that was prepared for the signing. Once the
command has been run, the Proseware.app file has been modified with a signature. This file is then used
when publishing the extension.

SignTool sign /f C:\Certificates\MyCert.pfx /p MyPassword /t


http://timestamp.verisign.com/scripts/timestamp.dll “C:\NAV\Proseware.app”

IMPORTANT
It's recommended to use a time stamp when signing the APP package file. A time stamp allows the signature to be
verifiable even after the certificate used for the signature has expired. For more information, see Time Stamping
Authenticode Signatures. Depending on the certification authority, you may need to acquire a specific certificate in order
to time stamp, an Extended Validation certificate from DigiCert for example.

NOTE
If you are using the BCContainerHelper PowerShell module to run Dynamics 365 Business Central on Docker, you can use
the function Sign-BCContainerApp to perform all the steps above.

Self-signed certificate
For testing purposes and on-premises deployments, it's acceptable to create your own self-signed certificate
using the New-SelfSignedCertificate cmdlet in PowerShell on Windows 10 or MakeCert.
The following example illustrates how to create a new self-signed certificate for code signing:

New-SelfSignedCertificate –Type CodeSigningCert –Subject “CN=ProsewareTest”

The following (deprecated) MakeCert command is used to create a new self-signed certificate for code signing:

Makecert –sk myNewKey –n “CN=Prosewaretest” –r –ss my

See Also
Get Started with AL
Keyboard Shortcuts
AL Development Environment
Use Azure AD Authentication for Business Central
On-Premises Installations
2/6/2023 • 2 minutes to read • Edit Online

In addition to using Windows and NavUserPassword authentication, you can use Azure AD to authenticate and
publish in on-premises installations and containers from Visual Studio Code. Using Azure AD makes it possible
to mimic application lifecycle operations in an on-premises environment, while keeping the cloud-based Azure
AD authentication.
To enable Azure AD authentication, make sure to do as follows:
Use the primaryTenantDomain setting in the launch.json file to specify the URL of the Azure AD organization
or company associated with the Azure AD tenant. For more information, see Find tenant ID, domain name,
user object ID and JSON Files.
On the NST, you must ensure that the server is set up to use Azure AD as authentication mechanism. For
more information, see User Authentication with Azure AD for Single Sign-on.
Furthermore, if the Allowed Extension Target Level setting is set to Cloud , the server setting
ForceExtensionAllowedTargetLevel must be set to true . If the Allowed Extension Target Level setting is set
to OnPrem , it isn't necessary to set ForceExtensionAllowedTargetLevel . For more information, see Microsoft
Dynamics 365 Business Central Server Configuration.

See also
JSON Files
User Authentication with Azure AD for Single Sign-on
Find tenant ID, domain name, user object ID
Testing the Application Overview
2/6/2023 • 7 minutes to read • Edit Online

Before you release your Business Central application, you should test its functionality to ensure it works as
expected. Testing is an iterative process. It's important and helpful to create repeatable tests that can be
automated. This article describes the features in Business Central to help you test the business logic in your
application and provides best practices for testing.
For a walkthrough concerning advanced extension testing, see Testing the Advanced Extension Sample.
Business Central includes the features that are listed below to help you test your application.

Environment testing support and limitations


The extent to which you can run automated tests will depend on your Business Central solution type and
environment. The following table gives an overview.

B USIN ESS C EN T RA L
SO L UT IO N EN VIRO N M EN T T EST IN G A L LO W ED M O RE DETA IL S

Online Production Running tests isn't allowed


because it might have an
adverse effect on your
business. Testing can
incidentally invoke external
systems, like CDS, PayPal,
and web hook
subscriptions. Invoking
these systems may slow
down the solution for other
users or cause data
corruption.

Sandbox You can use a sandbox


environment to run tests
manually to verify
functionality on an
environment. Running a
large number of tests or
tests that take a long time
(more than 15 minutes per
test method) isn't allowed.
It's recommended that you
don't run tests more than
one or two hours a day.
B USIN ESS C EN T RA L
SO L UT IO N EN VIRO N M EN T T EST IN G A L LO W ED M O RE DETA IL S

On-premises Production For Business Central on-


premises, running
automated tests is only
possible with a Partner
license or a license that
includes the Application
Builder module.

You can disable the ability


to run tests by turning off
Enable Test Automation
(TestAutomationEnabled) on
the Business Central Server
instance. For more
information, see
Configuring Business
Central Server - General
Settings.

Container-based This setup should be the


development environment default environment for
running large number of
tests or setting up CI/CD
gates. For more
information, see Running a
Container-Based
Development Environment
or Running Tests In
Containers.

Test Codeunits and Test Methods


You write tests as AL code in methods of codeunits that are configured to be test codeunits. Test codeunits have
the SubType Property set to Test . There are three types of methods that you can add in a test codeunit: test,
handler, and normal. Each method type is used for a specific purpose and behaves differently. When a test
codeunit runs, it executes the OnRun trigger, and then executes each test method in the codeunit. The outcome
of a test method is either SUCCESS or FAILURE.
This pattern doesn't apply to test isolation and isn't recommended as a method for running tests.
For more information about test codeunits and test methods, see Test Codeunits and Test Methods.

Test runner codeunits


You use test runner codeunits to manage the execution of test codeunits and to integrate with other test
management, execution, and reporting frameworks. By integrating with a test management framework, you can
automate your tests and enable them to run unattended.
Test runner codeunits are codeunits that have the SubType Property set to TestRunner .
Test runner codeunits include the following triggers:
OnRun Trigger
OnBeforeTestRun Trigger
OnAfterTestRun Trigger
In the OnRun trigger, you enter the code to run the codeunits. It runs when you execute the codeunit and before
the test methods run. You can use the OnBeforeTestRun and the OnAfterTestRun triggers to do
preprocessing and postprocessing, such as initialization or logging test results.
For more information about test runner codeunits, see Test Runner Codeunits.

TIP
You can reuse test runners from Test Runner module in the Microsoft/ALAppExtensions GitHub repo. You can also use the
repo to request for the new functionality.

Test pages
Test pages mimic actual application pages but don't present any UI on a client computer. Test pages let you test
the code on a page by using AL to simulate user interaction with the page.
There are two types of test pages:
TestPage, which is a regular page and can be of any kind. It includes page parts and subpages as well.
TestRequestPage, which represents the request page on a report.
You access the page's fields and properties or a field by using the dot notation. You can open and close test
pages, do actions on the test page, and navigate around the test page by using AL methods. For more
information, see Testing Pages.

UI handlers
To create tests that can be automated, you must handle cases when user interaction is requested by the code
that is being tested. UI handlers run instead of the requested UI. UI handlers provide the same exit state as the
UI. For example, a method that has the ConfirmHandler Attribute set, handles Confirm Method calls. If code that
is being tested calls the Confirm Method, then the ConfirmHandler method is called instead of the Confirm
Method. You can write code in the ConfirmHandler method to verify that the expected question is displayed by
the Confirm Method. You can also write AL code to return the relevant reply.
For each page and report that you want to handle, you need to create a specific handler for the page and a
specific report handler for the report.
If you run a test codeunit from a test runner codeunit, then any unhandled UI in the test methods of the test
codeunit causes a failure of the test. If you don't run the test codeunit from a test runner codeunit, then any
unhandled UI is displayed as it typically would.
For more information, see Create Handler Methods.

ASSERTERROR Keyword
You use AssertError statements in test methods to test how your application behaves under failing conditions.
These statements are called positive and negative tests. The AssertError keyword specifies that an error is
expected at run time in the statement that follows the AssertError keyword.
If a simple or compound statement that follows the AssertError keyword causes an error, then execution
successfully continues to the next statement in the test method. You can get the error text of the statement by
using the GETLASTERRORTEXT Method.
If a statement that follows the AssertError keyword doesn't cause an error, then the AssertError statement
causes the following error and the test method that is running produces a FAILURE result.
IMPORTANT
Use ASSERTERROR in a test code only. It isn't allowed or supported in the production code.

Example
To create a test method to test the result of a failure of a CheckDate method that you've defined, you can use the
following code. This example requires that you create a method called CheckDate. This method checks whether
the date is valid for the customized application. You also create the following text constant, Date variable
InvalidDate, and Text variable InvalidDateErrorMessage.

InvalidDate := 010184D;
InvalidDateErrorMessage := 'The date is outside the valid date range.';
ASSERTERROR CheckDate(InvalidDate);
if GETLASTERRORTEXT <> InvalidDateErrorMessage then
ERROR('Unexpected error: %1', GETLASTERRORTEXT);

Testing best practices


We recommend the following best practices for designing your application tests:
Test code should be kept separate from the code that is being tested. That way, you can release the tested
code to a production environment without releasing the test code.
Test code should determine that the code works as intended both under successful and failing conditions.
These tests are called positive and negative tests. The positive tests validate that the code being tested
works as intended under successful conditions. The negative tests validate that the code being tested
work as intended under failing conditions.
1. In positive tests, the test method should validate the results of application calls, such as return
values, state changes, or database transactions.
2. In negative tests, the test method should validate that the intended errors occur, error messages
are presented, and data has the expected values.
Automated tests shouldn't require user intervention.
Tests should leave the system in the same well-known state as when the test started. This way, you can
rerun the test or run other tests in any order and always start from the same state.
Test execution and reporting should be fast and able to integrate with the test management system. This
way, the tests can be used as check-in tests or other build verification tests. These other tests typically run
on unattended servers.
Create test methods that follow the same pattern:
1. Initialize and set up the conditions for the test.
2. Invoke the business logic that you want to test.
3. Validate that the business logic worked as expected.
Only use hardcoded values in tests when you really need it. For all other data, consider using random
data.
For example, you want to test the Ext. Doc. No. Mandatory field in the Purchases & Payables Setup table.
To do this, you need to create and post typical purchase invoice. The typical purchase invoice line specifies
an amount. For most tests, it doesn't matter exactly what amount. For inspiration, see the use of the
GenerateRandomCode method in the tests that are included in the TestToolkit folder on the Business
Central product media. For more information, see Random Test Data.

TIP
Use the Any module in the Microsoft/ALAppExtensions GitHub repo to generate pseudo-random values during
test set-up. This module generates the same set of numbers, allowing you to reproduce test failures.

Tests should be readable and fast to execute. We recommend that test codeunits run under 2 minutes,
and that you don't add more than 100 test methods to the codeunit.

See Also
Testing Pages
Create Handler Methods
Test Codeunits and Test Methods
Application Testing Example: Testing Purchase Invoice Discounts
Random Test Data
Testing the Advanced Extension Sample
Create Test Codeunits and Test Methods
2/6/2023 • 2 minutes to read • Edit Online

In Dynamics 365 Business Central, you can create test codeunits and then test methods in the test codeunits.
Test codeunits are codeunits that have the SubType Property set to Test . You write tests as Al code in the
methods inside of the test codeunits. There are three types of methods that you can add in a test codeunit: test,
handler, and normal. Each method type is used for a specific purpose and behaves differently. When a test
codeunit runs, it runs the OnRun trigger, and then runs each test method in the codeunit.
By default, each test method runs in a separate database transaction, but you can use the TransactionModel
Attribute on test methods and the TestIsolation Property on test runner codeunits to control the transactional
behavior.
The results of a test codeunit and of the individual test methods are displayed in a message window, but you can
use the OnAfterTestRun Trigger on a test runner codeunit to capture the results. The outcome of a test method is
either SUCCESS or FAILURE. If any error is raised by either the code that is being tested or the test code, then the
global outcome of the test codeunit is FAILURE and the error is included in the results log file.
The difference between a normal codeunit and a test codeunit is their execution at runtime. When a normal
codeunit is run, if one of its methods fails, then the codeunit is terminated. When a test codeunit is run, even if
the outcome of one test method is FAILURE, the next test methods are still running.
The methods in a test codeunit can be one of the following types:

TYPE DESC RIP T IO N

Test method You use test methods that include AL code that tests the
business logic in the application, where each method covers
a transaction. You declare the Test Attribute on the method.

Handler method You use handler methods to automate tests by handling


instances when user interaction is required by the code that
is being tested by the test method. In these instances, the
handler method is run instead of the requested user
interface. The handler method should simulate the user
interaction for the test case, such as validating messages,
making selections, or entering values. You declare a handler
type attribute on the method. For more information, see
Create Handler Methods

Normal method You use normal methods to structure the test code by using
the same design practices and principles as methods in other
codeunits of the application. You declare the Normal
Attribute on the method.

See Also
Testing the Application
Create Handler Methods
2/6/2023 • 2 minutes to read • Edit Online

You can create test codeunits, test methods, and test pages to test your application. We recommend that you
create tests that can be automated. To create automated tests, you must write code to handle all UI interactions
so that the tests don't require user interaction when they're running. To do this, you create special handler
methods.
You can use the following handler methods:

M ET H O D T Y P E P URP O SE SIGN AT URE

MessageHandler Handles Message statements. <Function name>(<Message>:


Text[1024])

ConfirmHandler Handles Confirm statements. <Function name>(<Question>:


Text[1024]; var <Reply>: Boolean)

StrMenuHandler Handles StrMenu statements. <Function name>(<Options:


Text[1024]; var <Choice>: Integer;
<Instruction>: Text[1024])

PageHandler Handles specific pages that aren't run <Function name>(var <Page>: Page
modally. <page id>)

<Function name>(var <Page>:


TestPage <testpage id>)

ModalPageHandler Handles specific pages that are run <Function name>(var <Page>: Page
modally. <page id>; var <Response>: Action)

<Function name>(var <Page>: Page


<testpage id>)

ReportHandler Handles specific reports. If you create a <Function name>(var <Report>:


Repor tHandler method, then that Report <report id>)
method replaces all code for running
the report, including the request page,
and a RequestPageHandler isn't
called. Only create a
RequestPageHandler if you aren't
using a ReportHandler.

FilterPageHandler Handles a specific filter page. The <Function name>(var <Record1>:


FilterPageHandler tests the UI that is RecordRef)[, var <Record2>: RecordRef]
generated by a FilterPageBuilder Data [, ...]): Boolean
Type.

RequestPageHandler Handles the request page of a specific <Function name>(var <RequestPage>:


report. TestRequestPage)

HyperlinkHandler Handles specific hyperlinks. <Function name>(<Hyperlink>:


Text[1024])
M ET H O D T Y P E P URP O SE SIGN AT URE

SendNotificationHandler Handles Send statements. <Function name>(<TheNotification>:


Notification): Boolean

RecallNotificationHandler Handles Recall statements. <Function name>(<TheNotification>:


Notification): Boolean

SessionSettingsHandler Handles RequestSessionUpdate <Function name>(var


statements. <SessionSettings>: SessionSettings):
Boolean

How to create a handler method


To create a handler method, you set one of the handler attributes on a method. You must use the method
signature specified for the handler attribute that you're using, as illustrated in this code example.

[MessageHandler]
procedure MessageHandler(Message: Text[1024])
begin
Assert.IsTrue(StrPos(Message, MSG_HAS_BEEN_CREATED) > 0, Message);
end;

The parameters of the methods that are being handled are passed as parameters to the handler methods. For
example, when Message is called in a test method, the parameter of the Message method is passed as the
parameter of the MessageHandler method. For page and report handlers, the page, report, or request page is
passed as the parameter of the PageHandler , ModalPageHandler , Repor tHandler , or
RequestPageHandler .
You can call handler methods from methods that have the Test Attribute and then specify the handler methods
that it will use in the HandlerFunctions Attribute. The code inside the test method should simulate that the UI
was actually raised and some values entered or some actions were taken. You can specify more than one
handler method by separating the handler method names with a comma.

NOTE
Every handler method that you enter in the HandlerFunctions Attribute of a test method must be called at least one time
in the test method. If you run a test method that has a handler method listed that isn't called, then the test fails.

The following example shows a test method that uses the HandlerFunctions Attribute to call the
MessageHandler method.

[Test]
[HandlerFunctions('MessageHandler')]
procedure ApproveRequestForPurchCreditMemo()
var
PurchHeader: Record "Purchase Header";
begin
ApproveRequestForPurchDocument(PurchHeader."Document Type"::"Credit Memo");
end;

See Also
Testing the Application
AL Methods
Create Test Runner Codeunits
2/6/2023 • 2 minutes to read • Edit Online

You can create test runner codeunits to manage the execution of test codeunits and to integrate with test
management or test reporting frameworks. By integrating with a test management framework, you can
automate your tests and enable them to run unattended.
To create a test runner codeunit, create a codeunit and set the SubType Property to TestRunner .
To specify what changes in the database you want to roll back after the tests in the test runner codeunit execute,
set the TestIsolation Property.
Test runner codeunits include the following triggers:
OnRun Trigger
OnBeforeTestRun Trigger
OnAfterTestRun Trigger
In the OnRun trigger, you'll enter the code to run the codeunits. It runs when you execute the codeunit and
before the test methods run. You can use the OnBeforeTestRun and the OnAfterTestRun triggers to perform
preprocessing and postprocessing, such as initialization or logging test results. If you implement the
OnBeforeTestRun trigger, then it executes before each test method executes. If you implement the
OnAfterTestRun trigger, then it executes after each test method executes and also suppresses the automatic
display of the results message.

WARNING
The OnBeforeTestRun and OnAfterTestRun triggers always run in their own transactions, regardless of the value of
the TestIsolation Property, the value of the TransactionModel Property, or the outcome of a test method.

Example
This sample codeunit runs three test codeunits in the automated application test libraries.

codeunit 50101 TestRunnerCodeunit


{
Subtype = TestRunner;

trigger OnRun()
begin
Codeunit.RUN(Codeunit::"ERM Vendor Statistics");
Codeunit.RUN(Codeunit::"ERM Sales Quotes");
Codeunit.RUN(Codeunit::"ERM Dimension");

end;
}

You may want to define your test suite in a table and then write code in the test runner codeunit to iterate
through the items in the table. And then run each test codeunit. In that case, you can make use of the following
example.
codeunit 50102 TestRunnerCodeunit
{
Subtype = TestRunner;

trigger OnRun()
var
EnabledTestCodeunit: Record "CAL Test Enabled Codeunit";
Object: Record "Object";
begin
if EnabledTestCodeunit.FINDSET then
repeat
if Object.GET(ObjectType::Codeunit, '', EnabledTestCodeunit."Test Codeunit ID") then
CODEUNIT.RUN(EnabledTestCodeunit."Test Codeunit ID");
until EnabledTestCodeunit.NEXT = 0

end;
}

See Also
Testing the Application
Testing Pages
2/6/2023 • 3 minutes to read • Edit Online

You use test page objects to simulate user interactions with the application. You can:
View or change the value of a field on a test page.
View the data on page parts.
View or change the value of a field on a subpage.
Filter the data on a test page.
Perform any actions that are available on the page.
Navigate to different records.
You can create and open a test page in the following ways:
Declare a test page variable and then write AL code to open the test page by using one of the following
methods:
OpenNew Method (TestPage)
OpenEdit Method (TestPage)
OpenView Method (TestPage)
Create a PageHandler or ModalPageHandler method that has a test page parameter.
Write AL code to trap a call to open a test page by using the Trap Method (TestPage).

NOTE
You must consider how you set the TransactionModel Property to simulate the scenario that you want to test and to
return the database to its initial state after the test.

NOTE
Test methods and code on test pages run on the Dynamics 365 Business Central Server instance, even though they
simulate client interactions.

For more information about the AL methods that you use on a test page, see TestPage Data Type.

Access fields on test pages


You can access the fields on a test page by using the dot notation. For example, if you have a test page variable
named CustomerCard that represents the Customer Card page, then to access the Name field on the test page,
you'll write CustomerCard.Name in your code.
These fields are instances of the TestField Data Type, so you can use the corresponding AL methods to work with
them. For example, if you have a test page variable named CustomerCard that represents the Customer Card
page, then to assign the value of the No. field to a variable named CustNo , you write
CustNo := CustomerCard."No.".Value in your code. To write a value in the Address field of a Customer Card page,
you write CustomerCard.Address.Value := '<address>' in your code.

Access page parts and subpages


You access page parts and subpages on a test page by using the dot notation.
These are instances of the TestPart Data Type, so you can use the corresponding AL methods to work with them.
For example, to compare the value of the No. field on a page to the value of the No . field on a FactBox on the
page, you can write the following code.

if CustomerCard."No.".Value <> CustomerCard."Sales Hist. Sell-to FactBox"."No.".Value then


error("Page part data is not updated.");

Filtering data on test pages


To filter the data that can be accessed on a test page, you use AL methods corresponding to the TestFilter Data
Type instances. For example, to filter the customers on the Customer List page based on a range of values in
the No. field, you can write the following code.

CustomerList.Filter.SetFilter("No.", '20000..30000');

Invoking actions on test pages


Any action that is available on a page is also available on the test page that mimics the original page. You access
page actions by using the dot notation and the Invoke Method.
These are instances of the TestAction Data Type, so you can use the corresponding AL methods to work with
them. To access built-in actions, such as Yes, No, OK, or Cancel you can also call the Yes Method, No Method, Ok
Method and Cancel Method respectively, directly in the test page.

Navigate among records


To simulate moving to different items on a list page or to different records on a card page, you can use one of
the following navigation methods:
Next Method (TestPage)
Previous Method (TestPage)
First Method (TestPage)
Last Method (TestPage)
GoToRecord Method (TestPage) )
GoToKey Method (TestPage)
FindFirstField Method (TestPage)
FindNextField Method (TestPage)
FindPreviousField Method (TestPage)

See Also
Testing the Application
Testing the Advanced Sample Extension
Create Handler Methods
2/6/2023 • 2 minutes to read • Edit Online

You can create test codeunits, test methods, and test pages to test your application. We recommend that you
create tests that can be automated. To create automated tests, you must write code to handle all UI interactions
so that the tests don't require user interaction when they're running. To do this, you create special handler
methods.
You can use the following handler methods:

M ET H O D T Y P E P URP O SE SIGN AT URE

MessageHandler Handles Message statements. <Function name>(<Message>:


Text[1024])

ConfirmHandler Handles Confirm statements. <Function name>(<Question>:


Text[1024]; var <Reply>: Boolean)

StrMenuHandler Handles StrMenu statements. <Function name>(<Options:


Text[1024]; var <Choice>: Integer;
<Instruction>: Text[1024])

PageHandler Handles specific pages that aren't run <Function name>(var <Page>: Page
modally. <page id>)

<Function name>(var <Page>:


TestPage <testpage id>)

ModalPageHandler Handles specific pages that are run <Function name>(var <Page>: Page
modally. <page id>; var <Response>: Action)

<Function name>(var <Page>: Page


<testpage id>)

ReportHandler Handles specific reports. If you create a <Function name>(var <Report>:


Repor tHandler method, then that Report <report id>)
method replaces all code for running
the report, including the request page,
and a RequestPageHandler isn't
called. Only create a
RequestPageHandler if you aren't
using a ReportHandler.

FilterPageHandler Handles a specific filter page. The <Function name>(var <Record1>:


FilterPageHandler tests the UI that is RecordRef)[, var <Record2>: RecordRef]
generated by a FilterPageBuilder Data [, ...]): Boolean
Type.

RequestPageHandler Handles the request page of a specific <Function name>(var <RequestPage>:


report. TestRequestPage)

HyperlinkHandler Handles specific hyperlinks. <Function name>(<Hyperlink>:


Text[1024])
M ET H O D T Y P E P URP O SE SIGN AT URE

SendNotificationHandler Handles Send statements. <Function name>(<TheNotification>:


Notification): Boolean

RecallNotificationHandler Handles Recall statements. <Function name>(<TheNotification>:


Notification): Boolean

SessionSettingsHandler Handles RequestSessionUpdate <Function name>(var


statements. <SessionSettings>: SessionSettings):
Boolean

How to create a handler method


To create a handler method, you set one of the handler attributes on a method. You must use the method
signature specified for the handler attribute that you're using, as illustrated in this code example.

[MessageHandler]
procedure MessageHandler(Message: Text[1024])
begin
Assert.IsTrue(StrPos(Message, MSG_HAS_BEEN_CREATED) > 0, Message);
end;

The parameters of the methods that are being handled are passed as parameters to the handler methods. For
example, when Message is called in a test method, the parameter of the Message method is passed as the
parameter of the MessageHandler method. For page and report handlers, the page, report, or request page is
passed as the parameter of the PageHandler , ModalPageHandler , Repor tHandler , or
RequestPageHandler .
You can call handler methods from methods that have the Test Attribute and then specify the handler methods
that it will use in the HandlerFunctions Attribute. The code inside the test method should simulate that the UI
was actually raised and some values entered or some actions were taken. You can specify more than one
handler method by separating the handler method names with a comma.

NOTE
Every handler method that you enter in the HandlerFunctions Attribute of a test method must be called at least one time
in the test method. If you run a test method that has a handler method listed that isn't called, then the test fails.

The following example shows a test method that uses the HandlerFunctions Attribute to call the
MessageHandler method.

[Test]
[HandlerFunctions('MessageHandler')]
procedure ApproveRequestForPurchCreditMemo()
var
PurchHeader: Record "Purchase Header";
begin
ApproveRequestForPurchDocument(PurchHeader."Document Type"::"Credit Memo");
end;

See Also
Testing the Application
AL Methods
Application Testing Example: Testing Purchase
Invoice Discounts
2/6/2023 • 4 minutes to read • Edit Online

Before you release a customized Dynamics 365 Business Central application to a production environment, you
must test the application. This walkthrough demonstrates how to use the test codeunits and test libraries to test
an application.

About this example


You have modified codeunit 70, Purch-Calc.Discount, which is a codeunit in the CRONUS International Ltd.
database. You want to test the functionality of the customized codeunit before you offer the customized
application for sale. You create a new test codeunit with new test methods to test the Purch-Calc.Discount
codeunit. During development, You use the application test libraries to help write a test with fewer lines of code.

Prerequisites
To complete this example, you will need:
Dynamics 365 Business Central with a developer license.
The CRONUS International Ltd. demo data company.
To import the Test Toolkit.

Task 1: Create the test codeunit and method


1. Create a new codeunit and specifies that it is a test codeunit.
2. Define the scenario that you want to verify, and add a test method to test the Purch-Calc.Discount
functionality.

TIP
By default, methods in test codeunits are test methods unless you specify otherwise.

Guidelines
In this example, the name of the test method consists of the tested functionality, Purchase Invoice
Discount Calculation, and relevant parameters that affect the test result. We recommend that you follow
this naming pattern for your test methods also. In our example, the following parameters are introduced:
PInv for the document that is tested, purchase invoices. You can apply the same test to purchase orders
or purchase credit memos. Also, we recommend that you have mirrored sets of tests for the sales area.
Above . It is a good practice to have tests for positive and negative scenarios. In this test, Isaac wants to
check that discount come into effect when the document amount is above a minimum amount. But the
amount in the document can be also less than or equal to the minimum amount.
Isaac first defines the test scenario [SCENARIO], then details it with the GIVEN-THEN-WHEN notation.
Finally, he adds the AL code.The code in this test method prepares the test data by setting a random
discount percent, a minimum amount, and a document amount. Then, it creates a purchase document
with a line and runs the Purch-Calc.Discount codeunit, which contains the code that is being tested.
Finally, it verifies the results of running the Purch-Calc.Discount codeunit and raises an error if the results
are not as expected.
You can create additional test methods in this test codeunit to test other aspects of vendor discounts.
These test methods should include negative tests, which validate that the code being tested works as
intended under failing conditions.

Task 2: Create a helper method


Tne next task is to create a helper method that generates data for the test. The helper method can be reused if
you decide to extend test coverage.
Guidelines
The code in the helper method prepares data for the test by creating a new vendor, setting up the invoice
discount, and creating a purchase document with an item. Because this helper method is not specific to the
test itself, you can reuse it for similar tests. For example, you can call it with other parameters and create a
purchase credit memo, or set up 0% discount, or create a document where the total amount is less than the
minimum amount that is specified in Vendor Invoice Disc. table.

NOTE
This test code does not guarantee that the state of the database after you run the test is the same as the state of the
database before you run the test.

Code
codeunit 50111 "ERM Vendor Discount"
{
// Specifies the codeunit to be a test codeunit
Subtype = Test;

trigger OnRun()
begin

end;

// Makes the method a test method


[Test]

// Adds the test logic to the test method


procedure PurchInvDiscCalculationPInvAbove()

var
PurchLine: Record "Purchase Line";
MinAmount: Decimal;
DocAmount: Decimal;
DiscountPct: Decimal;
PurchCalcDisc: Codeunit "Purch.-Calc.Discount";

begin
// [SCENARIO] "Inv. Discount Amount" should be calculated on Purchase Invoice (in LCY), where
Invoice amount is
// above the minimal amount required for invoice discount calculation.
// [GIVEN] Vendor with invoice discount percentage "D" for minimal amount "A" in LCY
// [GIVEN] Create purchase invoice with one line and amount >"A"
DiscountPct := RandomNumberGenerator.RandDec(100, 5);
MinAmount := RandomNumberGenerator.RandDec(1000, 2);
DocAmount := MinAmount + RandomNumberGenerator.RandDec(100, 2);
CreatePurchDocument(PurchLine, PurchLine."Document Type"::Invoice, DocAmount, MinAmount,
DiscountPct);
DiscountPct);
// [WHEN] Calculate invoice discount for purchase document (line)
PurchCalcDisc.RUN(PurchLine);
// [THEN] "Inv. Discount Amount" = Amount "A" * discount "D" / 100
PurchLine.Find;
Assert.AreEqual(Round(PurchLine."Line Amount" * DiscountPct / 100), PurchLine."Inv. Discount
Amount", PurchInvDiscErr);
end;

// Creates the test helper method


local procedure CreatePurchDocument(var PurchLine: Record "Purchase Line"; DocumentType: Option;
DocAmount: Decimal; MinAmount: Decimal; DiscountPct: Decimal)

var
VendorInvoiceDisc: Record "Vendor Invoice Disc.";
PurchaseHeader: Record "Purchase Header";
VendorNo: Code[30];

begin
// Create vendor
VendorNo := LibraryPurchase.CreateVendorNo;
// Create vendor invoice discount
VendorInvoiceDisc.Init;
VendorInvoiceDisc.Code := VendorNo;
VendorInvoiceDisc.Validate("Currency Code", '');
VendorInvoiceDisc.Validate("Minimum Amount", MinAmount);
VendorInvoiceDisc.Validate("Discount %", DiscountPct);
VendorInvoiceDisc.Insert(TRUE);
// Create purchase line
LibraryPurchase.CreatePurchaseDocumentWithItem(PurchaseHeader, Purchline, DocumentType, VendorNo,
'', 1, '', 0D);
PurchLine.Validate("Direct Unit Cost", DocAmount);
PurchLine.Modify(TRUE);
end;

var
RandomNumberGenerator: Codeunit "Library - Random";
LibraryPurchase: Codeunit "Library - Purchase";
Assert: Codeunit Assert;
myInt: Integer;
PurchInvDiscErr: Label 'The Purchase Invoice Discount Amount was not calculated correctly.';

See Also
Testing the Application
The Performance Toolkit Extension
2/6/2023 • 19 minutes to read • Edit Online

The Performance Toolkit extension is built for Independent Solution Vendors (ISVs) and Value Added Resellers
(VARs) who develop vertical solutions and customize Business Central for their customers. Because things
change between released versions, it's important that ISVs and VARs can test the performance of their solutions
to ensure that new versions don't introduce performance regressions when the volume of users grows. To help,
the Performance Toolkit lets developers simulate workloads in realistic scenarios to compare performance
between builds of their solutions.
The Performance Toolkit extension helps answer questions such as, "Does my solution for Business Central
support X number of users doing this, that, and the other thing at the same time?"
The extension doesn't answer questions such as, "How many orders can Business Central process per hour?"

Components of the Performance Toolkit extension


The Performance Toolkit is actually three separate extensions that work together. The following table describes
the extensions and where to get them.

C O M P O N EN T DESC RIP T IO N

Performance Toolkit This is the recommended place to start because this


extension makes it easier to get going with performance
tests. The extension is free and can be installed from the
Extensions Marketplace for Visual Studio Code. This
extension can set up a new BCPT project that targets your
environment, and it includes BCPT-SampleTests and the
PowerShell scripts for simulating scenarios. It also allows you
to run your scenarios from Visual Studio Code.

IMPORTANT: You can use the toolkit only in sandbox


environments and Docker images. You can't use it in a
production tenant. Currently, only Windows is supported.

Performance Toolkit Free and available on AppSource.

PowerShell Scripts A command line tool for simulating multiple users signing in
and interacting with Business Central.

BCPT-SampleTests Free and available on the ALAppExtensions repository on


GitHub. These tests are intended to provide inspiration for
creating your own tests. You can't use them for actual
testing.

Combined, the extensions provide the following:


A framework for defining a set of tests or scenarios to run in parallel. The framework also logs results and
lets you import and export suite definitions.
Predefined sample tests that cover basic scenarios, which can also serve as inspiration for other tests that
suit your customer environments.
A command line tool that must be installed on a client computer. To simulate multiple users signing in and
using pages, you must start those scenarios from outside Business Central. The command line tool will run
the number of concurrent client sessions that is specified in the suite.
A VSCode extension that helps setting up your BCPT project and allows you to run your suites from VSCode.

Before you start


To use the Performance Toolkit, you must be assigned to the BC PERF. TOOLKIT permission set in Business
Central.

Get started
There are two ways to get started with the Performance Toolkit:
The recommended way is to install the Performance Toolkit extension from the Extension Marketplace in
Visual Studio Code. This extension is purpose-built to make it easy to set up the toolkit and start testing
performance.
If you want to set up the toolkit yourself, install the toolkit from AppSource via the Extensions Marketplace
page in Business Central, get the test samples from GitHub and download the DVD to get the PowerShell
scripts. This method is useful, for example, if you can't install the extension in Visual Studio Code or your
environment is not supported. Learn more about getting the scripts at Run using the PowerShell scripts.
The following steps provide an overview of how to get started. This article describes each step in more detail.
1. Install the Performance Toolkit extension in Visual Studio Code.
2. In Visual Studio Code, prepare your BCPT project and set up the Performance Toolkit extension on your
environment.
3. Write tests for the scenarios to simulate.
4. In Business Central, configure a BCPT suite.
Install the Performance Toolkit extension in Visual Studio Code

NOTE
Remember that you can't install the extension in a production environment.

1. In Visual Studio Code, open the Extension Marketplace , search for Performance Toolkit , and then
install the extension.
2. Create a project by running the BCPT Setup new Business Central Performance Toolkit project
command.

NOTE
If third-party extensions are installed, the toolkit will renumber the tests to avoid conflicts.

3. Choose whether to test in a Docker or online (SaaS) environment. Use Docker for Business Central on-
premeses.
4. Sign in to your Business Central, and choose your environment.
5. Specify the directory to create the BCPT project in.
When you choose OK , the extension verifies that the following Performance Toolkit components are
installed in your Business Central. If the components aren't installed, the extension will install them.
The Performance Toolkit.
The sample test cases.
The PowerShell scripts.
6. When installation is complete, choose Open a new window to open your project.
Create codeunits for your test scenarios
The test scenarios that the extension provides are meant to serve as inspiration for creating your own tests. To
test your environment, you'll need to write your own scenarios. A test scenario is a codeunit of either a Normal
or Test subtype.
If the subtype is Normal, the test scenario should be defined in the OnRun trigger because the Performance
Toolkit uses the codeunit to run the test scenario. These codeunits are useful when you want to write a scenario
without the involvement of pages. An example is shown below.

codeunit 50000 "Create Sales Order"


{
var
BCPTTestContext: Codeunit "BCPT Test Context";

trigger OnRun();
var
Customer: Record Customer;
*SalesHeader: Record "Sales Header";*
begin
Customer.FindFirst();
*SalesHeader.Init();*
*SalesHeader."Document Type" := SalesHeader."Document Type"::Order;*
*SalesHeader.Insert(true);*
BCPTTestContext.EndScenario('Add Order');
BCPTTestContext.UserWait();
BCPTTestContext.StartScenario('Enter Account No.');
*SalesHeader.Validate("Sell-to Customer No.", Customer."No.");*
*SalesHeader.Modify(true);*
BCPTTestContext.EndScenario('Enter Account No.');
BCPTTestContext.UserWait();

To interact with pages and make the tests more realistic, define a codeunit of the subtype Test and use Test
Pages. The following code example shows the main difference between normal and test codeunits.

codeunit 50000 "Create Sales Order"


{
*Subtype = Test;*

var
BCPTTestContext: Codeunit "BCPT Test Context";

trigger OnRun();
var
Customer: Record Customer;
*SalesOrder: TestPage "Sales Order";*
begin
Customer.FindFirst();
*SalesOrder.OpenNew();*
*SalesOrder."No.".SetValue('');*
BCPTTestContext.EndScenario('Add Order');
BCPTTestContext.UserWait();
BCPTTestContext.StartScenario('Enter Account No.');
*SalesOrder."Sell-to Customer No.".SetValue(Customer."No.");*
BCPTTestContext.EndScenario('Enter Account No.');
BCPTTestContext.UserWait();
TIP
We recommend that you only write scenarios using test pages for scenarios in which the client behavior is predictable. For
example, if an unexpected dialog shows up during the test, the test will fail with an exception.

Tests can use the StartScenario and EndScenario functions on the BCPT Test Context codeunit to log when
the scenario you're measuring started and stopped. These scenarios can also be nested, as shown in the earlier
example. Here we have a top level scenario for Add order, which contains sub-scenarios, such as Enter Account
No.. This allows you to perform overall measurements and more detailed measurements.
To simulate delays between user actions and make your tests more realistic, call the UserWait() function while
moving between fields. When using Business Central, an implicit Commit() is called for every interaction. Tests
should simulate the implicit Commit() by calling an explicit Commit() .

NOTE
The UserWait function will call the commit, so you don't need to do it yourself.

You can also specify parameters that you can provide for your tests. This is useful when you want to be able to
change certain behavior of your test. For example, you might want to change the number of sales lines you add
to a sales order. To enable parameters, implement the BCPT Test Param. Provider interface. The following
example shows how to implement the interface.

codeunit 50000 "Create PO with N Lines" implements "BCPT Test Param. Provider"
{
var
BCPTTestContext: Codeunit "BCPT Test Context";
NoOfLinesParamLbl: Label 'Lines';
ParamValidationErr: Label 'Parameter is not defined in the correct format. The expected format is
"%1"', Comment = '%1 = Format';
NoOfLinesToCreate: Integer;

trigger OnRun();
begin
...
end;

procedure GetDefaultParameters(): Text[1000]


begin
exit(copystr(NoOfLinesParamLbl + '=' + Format(10), 1, 1000));
end;

procedure ValidateParameters(Parameters: Text[1000])


begin
if StrPos(Parameters, NoOfLinesParamLbl) > 0 then begin
Parameters := DelStr(Parameters, 1, StrLen(NoOfLinesParamLbl + '='));
if Evaluate(NoOfLinesToCreate, Parameters) then
exit;
end;
Error(ParamValidationErr, GetDefaultParameters());
end;
}

Next, extend the BCPT Test Param. Enum to make it available in the Performance Toolkit.
enumextension 50000 "Test Codeunits with Params" extends "BCPT Test Param. Enum"
{
value(50000; "50000")
{
Implementation = "BCPT Test Param. Provider" = "Create PO with N Lines";
}
...
}

Learn more about writing test scenarios at Testing the Application Overview.
Configure a BCPT suite
Configure a suite for the scenario that you want to simulate. When you configure a suite, you'll need to specify:
What tests to run and, if applicable, with what parameters.
How many concurrent sessions you want to simulate for each test.
The duration of the scenario.
Single and multiple sessions
Typically, you'll want to run the suite for multiple sessions at the same time. After you configure the suite, you
can do that by using the Star t action. You can also use the Visual Studio Code extension or PowerShell scripts.
Learn more at Run a test suite using the Visual Studio Code extension.
To do a quick test, for example, during the development phase, choose the Star t in Single Run mode action to
run all your tests (suite lines) one time. It will also skip the user delays. Single Run mode lets you monitor the
number of SQL statements between runs and define baselines, and gives you quick feedback that can help
identify regressions early on.
You can run up to 500 sessions at the same time for a test suite. The Total No. of Sessions field shows how
many sessions will be created when you run the suite.
Run tests in the background and foreground
On the suite lines, the Run in Foreground checkbox lets you run tests in the foreground rather than as a
background task. You can specify this for each individual suite line. However, if your test involves UI interactions,
then it must run in the foreground. From the client, it's only possible to have one foreground test running at a
time. If multiple lines have the run in foreground option enabled, they will run sequentially. Background tests
will still run in parallel.

NOTE
If you must run multiple foreground tests in parallel, you must use the Visual Studio Code extension or the PowerShell
scripts.

Prepare your suite


The settings to configure a suite depend on the environment that you want to simulate. The following procedure
provides an example for testing multiple sessions, but the steps also apply to a single run.
1. Search for BCPT Suites , and choose the related lik.
2. Choose New to open the BCPT Suite page.
3. In the Code , Description , and Tag fields, provide an identifier, some information about the test, and a
tag that you can use to find the results of the suite on the Log Entries page. Tags are useful if you want
generate different sets of log entries from a suite. An example could be to measure performance before
and after installing extensions. Use the tag to differentiate between those two runs.
4. To define the timing for the run, follow these steps.
a. The 1 Work Day Corresponds to field works with the Duration (minutes) field to update the
Work Date Star ts at field. Use the 1 Work Day Corresponds to field to test processes that have
deadlines, such as payments. The duration can be up to 240 minutes.
b. The Default Min. User Delay and Default Max. User Delay fields let you simulate pauses
between actions. You must specify a delay. Between each iteration, for example when creating sales
orders, you can define a Delay (Delay between iterations) before the test starts on the next sales
order. The delay can be Fixed or Random . Delays aren't included in the results for run times.
5. Configure lines for the suite. The lines will contain some of the settings from the header. Updating the
values on the lines will also update the header.
a. If your test supports parameters, in the Parameters field, enter the parameters for your test. The
Parameter field must not contain spaces.
b. In the No. of Sessions field, enter the number of concurrent users to simulate in the workflow.
c. In the Min. User Delay (ms) and Max. User Delay (ms) fields, specify how long to pause between
actions. When you run a suite in Single Run mode, user delays are ignored.
d. In the Delay between interactions (sec) field, specify how long to pause between each run of the
codeunit for each session. Use this field to simulate how much work each user do. If one user creates
15 sales orders an hour, then you would need ~240 seconds (4 minutes) of delay between each test to
achieve that throughput.
e. In the Delay Type field, specify whether to use a fixed or random delay. If you choose Fixed , the test
will pause for the number of seconds specified in the Delay between iterations (sec) field.

Test performance
There are two ways to run BCPT suites.
Directly from Business Central.
By using the Visual Studio Code extension or Powershell scripts.
Known limitations
There are a couple of limitations for running BCPT suites.
If you run it from the client, you can only run one session at a time in the foreground.
Depending on whether you're environment is on-premises, Docker, or online, there might be a limit to the
number of sessions you can run at the same time in the background. Typically, the default number of
sessions is 10 . Learn more at Operational Limits for Business Central Online.
If your BCPT suite runs more than one session in the foreground, or more than 10 sessions at the same time in
the background, you must run the suite from the Visual Studio Code extension or PowerShell. Learn more at
Run using the PowerShell scripts.
To run a test in Single Run mode
The following steps provide an example of how to run a test in Single Run mode.
1. On the BCPT Suites page, choose New .
2. In the Code field, enter a name for the test suite. In this example, we'll use PreTest .
3. In the Tag field, enter something that will make it easy to identify the suite later when you analyze the
results.
4. The fields for duration and delays aren't used for Single Run mode, so we'll leave their default values.
5. On the BCPT Suit Lines FastTab, choose the test suite for your component.
6. In this example, we're calculating the total weight of the items on a sales order, so we'll use the Sales
Order page test with a parameter that creates four lines. The parameter looks as follows: Lines=4.
7. Clear the Run in Foreground checkbox. This will run the test suite in a background thread.
8. Choose Star t in Single Run mode .
9. To set your baseline after the run completes, in the Base Version field, enter 1 .

TIP
If you run the test again you'll have delta values on the test line. Learn more at Analyze the results. You can reset
the baseline to any version, and run as many tests as needed.

Run a test suite using the Visual Studio Code extension


Running suites from the Visual Studio Code extension gives you realistic simulations of multiple people working
at the same time. To offer a seamless experience, we have provided a command in the Visual Studio Code
extension for startint.
1. In Visual Studio Code, run the BCPT: Run BCPT (Powershell) command.
2. Select the environment type.
3. Select the specific environment to target.
4. Enter the BCPT suite code to run.
5. Optional: If you're targeting an online sandbox environment, you might be prompted to sign in.
An internal PowerShell process should start and an output window will appear in Visual Studio Code that shows
output similar to this:

Run using the PowerShell scripts

NOTE
The the Performance Toolkit extension in Visual Studio Code automatically installs these PowerShell scripts. However, if you
aren't using the Performance Toolkit in Visual Studio Code, you'll need to download the scripts. The scripts are available in
the DVD in the Applications\testframework\TestRunner folder. To get there, follow these steps:
1. Go to Download the files.
2. Choose the link to the latest version of Business Central.
3. In the Resolution section, choose the link to the latest update.

Depending on what you want to do, there are several ways to start the test suite by using the PowerShell scripts.
Create the credential object.
$Credential = New-Object PSCredential -ArgumentList <user email>,(ConvertTo-SecureString -String <password>
-AsPlainText -Force)

Start tests in a Business Central online sandbox.

RunBCPTTests.ps1 -Environment PROD -AuthorizationType AAD -Credential $Credential -SandboxName <sandbox


name> -ClientId <AAD application ID> -TestRunnerPage 149002 -SuiteCode "TRADE-50U" -
BCPTTestRunnerInternalFolderPath <path to Internal folder>

Start tests in a Business Central on-premises database.

RunBCPTTests.ps1 -Environment OnPrem -AuthorizationType Windows -Credential $Credential -TestRunnerPage


149002 -SuiteCode "TRADE-50U" -ServiceUrl <webclient address> -BCPTTestRunnerInternalFolderPath <path to
Internal folder>

NOTE
When you use RunBCPTTests.ps1, there are a few important parameters to use.
-Environment - Specifies the environment the tests will be run in. The supported values are PROD , TIE , and
OnPrem . Default is PROD .
AuthorizationType - Specifies the authorization type needed to authorize to the service. The supported values are
Windows , NavUserPassword , and AAD .
SandboxName - Specifies the sandbox name. This is necessary only when the environment is either PROD or TIE .
Default is sandbox .
ServiceUrl - Specifies the base URL of the service. This parameter is used only in OnPrem environment. For
example, http://localhost:8080/PerformanceToolkit .
ClientId - Specifies the guid that the Business Central is registered with in Azure AD. To set up Azure AD, go to
https://github.com/microsoft/BCTech/tree/master/samples/PSOAuthBCAccess.

1. In Visual Studio Code, on the Explorer Pane, choose the script that you want to run.
2. Choose the type of environment you want to target.
3. Choose the environment to run the test in.
4. Enter the name of the BCPT suite that you want to run, and then choose OK .
In Business Central, you can check the status of the BCPT suite by choosing the Refresh action.

NOTE
When you run tests there's a two second delay between new sessions. The delay prevents locking issues when the users
are signing into Business Central.

Analyze the results


Results show on the BCPT Suite Lines FastTab. The following tables describe the fields that show results of the
current run, the baseline, and the delta between the two.
F IEL DS F O R C URREN T RUN DESC RIP T IO N

No. of Iterations How many times it ran. This will be 1 because we used the
Star t in Single Run Mode action.

Total Duration in (ms) How long it took to complete one iteration.

Average duration Equal to the Total Duration in (ms) field for the first run,
but after you run a test multiple times it's a result of the sum
of runs since your baseline.

No. of SQL statements The number of SQL statements generated for one run.

Avg. No. of SQL Statements Similar to the duration fields, for the first run this will be the
same as the No. of SQL statements field, but will become
averaged after subsequent runs.

The following table describes the fields related to the baseline.

F IEL DS F O R B A SEL IN E DESC RIP T IO N

No. of Iterations Base Not relevant for Single Run mode.

Total Duration Base (ms) The total duration of the baseline run.

Avg. Duration Base (ms) Not relevant for Single Run mode.

Avg. No. of SQL Statements Base The number of SQL statements in your base run.

The following table describes the fields that show the delta between the run and the baseline.

F IEL DS F O R T H E DELTA DESC RIP T IO N

Change in No. of SQL statements (%) The percent of difference between the baseline and the latest
run.

Changes in Duration (%) The change in measured time between a baseline and the
latest run.

NOTE
The first iteration of any run will show a higher number of SQL Statements because nothing has been cached.

Comparing runs in the Change Log


Before you run a test with the change log on, change the Tag field to Change log . When you explore the log
entries afterwards, either remove the filter on the Version No. field, or change it to only include the last two
runs. After exporting to Excel, select the tag as columns in the pivot table, use Operation as a filter, and set the
filter to Scenario .
Troubleshoot log entries
After running the suite, you can choose Log Entries to see what happened. Use the Show Errors and Show
sessions running at the same time as this actions to apply filters to the results. For example, filtering can
help troubleshoot errors by showing what a user was doing when an error occurred. By default, the page is
filtered to show the latest version, but you can change or remove the filter if you want to compare runs. You can
use the Open in Excel action to build dashboards that can help visualize performance results.
Log entries are listed in the order that they were created, which means that the different scenarios are mixed.
Each run is identified by the value in the Version No. fields.
The Operation column shows the individual measurements, where the term Scenario is used for running the
codeunit without the user wait time. The No. of SQL Statements column includes the SQL statements that
were issued by the scenario and system activities, such as retrieving metadata. The counts exclude the log
entries themselves. To drill down to a single session, filter on the Session No. field or choose Open in Excel to
create a pivot table and pivot chart for deeper analysis.
Example: Evaluate SQL calls and timing in Single Run mode
This example shows how to use Single Run mode for performance regression testing (PRT) between changes to
code, to evaluate SQL calls and timing. While developing a new extension, you often start out with limited code
and may want to wait to do a larger benchmark test with simulated concurrent users until you’re closer to
having a full, end-to-end scenario. You can use the Star t in Single Run Mode action to perform a limited test,
for example, on a new extension. Single Run mode will still provide things like a baseline, the ability to run the
test in the background, and give you instant feedback.
The data that the runs generate is persisted in the database. If the database is maintained, you can set previous
runs as baseline.

TIP
If you attach an Application Insights key or connection string in the admin center for online or Business Central Server for
on-premises then the log entries are also shown in the Application Insights ID.

See Also
Testing the Application Overview
Development in AL
Best Practices for AL
FAQ about Testing your Business Central App
2/6/2023 • 4 minutes to read • Edit Online

This section contains answers to frequently asked questions about testing your app when you submit an app for
Business Central.

Since my app goes through validation, do I really need to thoroughly


test my app?
Yes. It's your app and you're the expert, so you should have a vested interest in high quality. The main goal of
validation is to ensure app code is meeting requirements and policy. The testing done during validation is only
to ensure good user experience on the most common app scenarios. We don't test every scenario of an app.
Using customers to find bugs isn't the proper approach.

Is it ok to submit my app for validation before we complete our own


testing?
No. Please, don't submit your app for validation until it has been 100% tested. This will lead to many delays in
the validation process otherwise. Also, it wastes time and resources.

Is it ok to test my AppSource app in an on-premises environment?


No. You must test your app using Business Central online. Although Business Central online and on-premises
are similar, they aren't the exact same. If you only test on-premises, invariably issues will be found in our
validation testing.

Does it really matter what version of Business Central I test on before


submitting my app for validation?
Yes. It's critical that you always test on the latest version at the time when you're ready to submit for validation.
Testing on the wrong version usually leads to validation failure. For example, let’s say the latest version of
Business Central is 15.4 at the time when you submit for validation you tested on 15.0. The product has changed
between those versions, and deprecated features or other changes could result in your app behavior changing.
We recommend that you consider using Docker containers. Use the Get-BcArtifactUrl function in the
BCContainerHelper PowerShell module to give you the artifact URL for the latest sandbox build for the specified
country. You don’t have to figure out what product version is active at time of submission. That function does it
for you.

How thorough should our testing be?


You should always test with 100% coverage, or at least as close to 100% as you can get. The testing should be a
combination of automated and manual tests. The apps with good testing infrastructure behind them are the
most successful.

Do I have to test on every country that I intend to support with my


app?
Yes. If you support multiple countries, test your app on every country. Each country's code base is slightly
different from both the base application and other countries. It's critical to make sure that the app publishes,
syncs, and installs on every country you support. Because an app installs fine on one country doesn’t mean it
will publish/install fine on another. We have seen many times where it passes on one but fails on another during
our validation.

Do you have recommendations on maintenance testing of our apps?


Yes. You should be testing your apps against our various build branches. Through Docker, you have access to our
latest public sandbox builds and through the "Ready! for Dynamics 365 Business Central" program on Microsoft
Collaborate you can also get access to Next Minor and Next Major builds. Test often, especially against the Next
Minor build. This allows you to catch any bugs that may arise from core changes in the product.

I only made minor code changes in my updated app. Can I test just
these changes?
No. You should always test 100% coverage no matter what. Testing only what you changed isn't the correct
approach. Even minor changes can lead to breaking changes where you least expect it.

Do I need to do upgrade testing?


Yes, this is a must. If an app fails to upgrade, customers are unable to get your updated app. This is one of the
common failures we see today in validations. You should want your app upgrade to work optimally.

Any recommendations on upgrade testing?


Test the upgrade with extensive app data included. Many of the upgrade failures for customers are data related.
The upgrade fails because specific data scenarios weren't considered for testing. Or worse, the upgrade
succeeds, and data is lost.

Do I only need to do upgrade testing from previous version to


current?
No. It's important you test from various previous versions of your app. This is because we don't automatically
upgrade apps for minor releases. You could have a tenant back on version 1.0.0.0 of your app and have to jump
all the way to version 1.0.0.5. We don’t guarantee direct upgrades of apps from their most previous version.

See also
FAQ about Updating your Business Central App
FAQ about Library & Dependency Apps in Business Central
Update Lifecycle for AppSource Apps FAQ
The Lifecycle of Apps and Extensions for Business Central
Sandbox Environments for Dynamics 365 Business
Central Development
2/6/2023 • 2 minutes to read • Edit Online

To get started developing for Dynamics 365 Business Central it is important to understand the different options
you have at hand. You can either choose to run a sandbox environment deployed as a Dynamics 365 Business
Central service, or you can run a container-based image either hosted as an Azure VM or locally. Both options
provide the AL development tools; the container-based sandbox additionally provides access to the C/SIDE
development tools. You can also choose to run a sandbox environment with production data using the Business
Central Admin Center . For more information, see Business Central Admin Center.

NOTE
Extensions that have been published to a sandbox environment from Visual Studio Code or created using Designer are
removed when the environment is updated or relocated within our service. For more information, see Production and
Sandbox Environments and FAQ for Developing in AL.

IMPORTANT
It is not supported to publish, from Visual Studio Code, an extension with the same identifiers as an extension published
to AppSource. Identifiers include the combination of appID and version or name, publisher, and version. If you do publish
such an extension, it can be removed at any time.

Development sandbox overview


The following table outlines the most important capabilities on the offered development sandbox environments
for Dynamics 365 Business Central.

C A PA B IL IT Y O N L IN E SA N DB O X C O N TA IN ER SA N DB O X

Deployment Dynamics 365 Cloud Service managed Azure VM or on-premises managed by


by Microsoft ISV/VAR

Production data Manually uploaded using Rapid Start Manually uploaded using Rapid Start
packages. Or, available through the packages
Business Central Admin Center.

Production services Manually configured Not available

Cost Part of the Business Central Locally hosted - free, Azure-hosted -


subscription cost incurred

Development Full capabilities of the development Full capabilities of the development


environment. environment.
Designer functionality, such as: Designer functionality, such as:
Add/Remove components, Add/Remove components,
Move components, Move components,
Set/clear Freeze pane, Set/clear Freeze pane,
Edit captions Edit captions
C A PA B IL IT Y O N L IN E SA N DB O X C O N TA IN ER SA N DB O X

Tools Visual Studio Code, Designer Visual Studio Code, Designer, on-
premise tools such as SQL Server
Management Studio, and C/SIDE.

Debugging Enabled Enabled

Database access No Yes

Extensions Must be manually installed. Must be manually installed.

From AppSource Available. Not available.

From File Available. Available.

From Visual Studio Code Available. Available.

Getting started
Based on the overview above and the requirements for your development environment, you can get started
with a sandbox by following the links below:
Online Sandbox with Demo Data
Online Sandbox with Production Data
Container Sandbox

See Also
Get Started with AL
Keyboard Shortcuts
AL Development Environment
Production and Sandbox Environments
Get started with the Container Sandbox
Development Environment
2/6/2023 • 3 minutes to read • Edit Online

Dynamics 365 Business Central offers a container-based image environment that enables access to the AL
development environment.
You set up a container sandbox by running the Container Sandbox Environment page from Dynamics 365
Business Central. You will have to decide whether you want an Azure-hosted or locally hosted container
sandbox. See the next section for details.

TIP
Dynamics 365 Business Central also offers an online sandbox. For more information, see Sandbox Environments for
Dynamics 365 Business Central Development.

Choosing an Azure-hosted or local-hosted container sandbox


When you set up the container sandbox, you can choose to host the sandbox on Microsoft Azure or on a local
computer. Both environments offer the same capabilities and use Docker to provide the infrastructure for the
container-based application. The difference is:
With Azure hosting, Docker is installed and configured for you. However, Azure hosting requires that you
sign up for an Azure subscription, and additional costs may be incurred for each container sandbox.
Local hosting requires that your computer is running Windows 10, Windows Server 2016, or Windows
Server 2019, and you install and configure Docker before setting up the container sandbox.

Set up an Azure-hosted container sandbox


1. If you you do not already have one, sign up for an Azure subscription.
To get a free subscription and read more information, see https://azure.microsoft.com.
2. In Dynamics 365 Business Central, choose the icon, enter Container Sandbox Environment , and
then select the relevant link.
3. Choose Host in Azure . If prompted, enter the user name and password of your Azure subscription.
The Azure portal opens to display a custom deployment form.
4. Fill out the required fields on the form, and then select Purchase .

NOTE
You must set the Accept Eula setting to Yes in order to continue.

Set up a local-hosted container sandbox


1. If not already done, install Docker.
To install and configure Docker, choose the version of Docker that is appropriate for the host operating
system:
For Windows 10, use Docker Community Edition. For more information, see Install instructions.
For Windows Server, use Docker Enterprise Edition. For more information, see Install instructions.
2. In Dynamics 365 Business Central, choose the icon, enter SANDBOX ENVIRONMENT
(CONTAINER) , and then select the relevant link.
3. Choose Host Locally .
4. Save the CreateBCSandbox.ps1 file to your computer.
5. Run Windows PowerShell ISE as an administrator.
6. Open the CreateBCSandbox.ps1 file.
7. Set the $containername = '' variable to the name that you want to give the container, for example
$containername = 'mybc' .
This name is only used internally in your envirorment for identification purposes.
8. Set the $accept_eula = '' variable to '$true' .
9. Press F5 to run the script.
The console pane displays the progress of the script. When the script has completed successfully,
information like the following will display:

...
Container IP Address: 172.22.147.63
Container Hostname : mybc
Container Dns Name : mybc
Web Client : http://mybc/BC/
Dev. Server : http://mybc
Dev. ServerInstance : BC

Files:
http://test:8080/ALLanguage.vsix

Initialization took 116 seconds


Ready for connections!
Reading CustomSettings.config from mybc
Creating Desktop Shortcuts for mybc

10. Write down or copy the following parameter/values from the console: Dev. Server , Dev. ServerInstance
, and Files . You will need this information later to set up Visual Studio Code for extension development.
You now have a container sandbox set up on your computer. The following shortcuts have been added to your
desktop:
<Container name> Web Client - opens the Web client for the your application in the container.
<Container name> PowerShell Prompt - opens a Windows PowerShell prompt in the container. This
gives you access to the Dynamics NAV (/powershell/business-central/overview), which you can run against
the container sandbox environment.
<Container name>Command Prompt - opens a Windows command prompt in the container.
For more information about working with a container sandbox, see Running a Container-Based Development
Environment.
Set up Visual Studio Code
After the container sandbox is set up, you must set up Visual Studio Code for extension development. To do this,
you need the values for Dev. Server , Dev. ServerInstance , and Files parameters that you retrieved from the
Windows PowerShell ISE console when you ran the CreateBCSandbox.ps1 script.
1. In Visual Studio Code, go to Extensions , and install the AL Language extension from the Marketplace.
You now have the AL Language extension enabled.
2. In Visual Studio Code, press Ctrl+Shift+P and then choose AL Go! .
3. Choose where to create the project, and then choose the Your own ser ver option.
4. Open the generated launch.json file, update the "server" setting with the value of the Dev. Server
parameter and the "serverInstance" setting with the value of the Dev. ServerInstance to reflect the
container you just created. For example:

"server": "http://mybc",
"serverInstance": "BC",
"authentication": "Windows",

5. Save the launch.json file.


You have now set up Visual Studio Code with the AL Language extension.

See Also
Running a Container-Based Development Environment
Working with Sandboxes and Entitlements
Sandbox Environments for Dynamics 365 Business Central Development
AL Development Environment
Working with Development Sandboxes and
Entitlements
2/6/2023 • 4 minutes to read • Edit Online

The experience that a user has in Dynamics 365 Business Central depends on the purchased subscription plan.
In Dynamics 365 Business Central, there are two main plans; the Essential and the Premium plan, plus a few
more. For more information, see Licensing in Dynamics 365 Business Central. For detailed information about
the Essential and Premium plans, see Business Central on the Microsoft Dynamics 365 site.
When you develop in a Docker sandbox, the Essential experience is automatically assigned to you (you set the
experience on the Company Information page), which makes it difficult to test how a user with the Premium
plan assigned will experience what you have developed.

NOTE
There is no license check in a Docker Sandbox except for on Purchase and Sales documents. There is a different behavior
in these documents as the TEAMMEMBER license has partial access. In particular Invoices, Orders, Quotes and Credit
Memos share the same table and the TEAMMEMBER license has access only to Quotes.

Setup for users with different plans


To mimic users with a specific subscription plan assigned, you can set them up with the user groups as detailed
in the table below. When you add user to the group, the permission sets defined for the group will apply to the
user. For more information, see To group users in user groups.

NOTE
In the table below non-default means not assigned by default, but the plan allows this to be assigned to the user.

USER N A M E
T H E T Y P E O F SUB SC RIP T IO N P L A N
A SSIGN ED TO T H E GIVEN USER USER GRO UP S

EXTERNALACCOUNTANT D365 EXT. ACCOUNTANT


EXTEND. MGT. - ADMIN (non-default)
Dynamics 365 Business Central External Accountant D365 TROUBLESHOOT (non-default)
D365 SECURITY (non-default)

PREMIUM D365 BUS PREMIUM


EXTEND. MGT. - ADMIN (non-default)
Dynamics 365 Business Central Premium D365 TROUBLESHOOT (non-default)
Dynamics 365 Business Central for IWs D365 SECURITY (non-default)

ESSENTIAL D365 BUS FULL ACCESS


EXTEND. MGT. - ADMIN (non-default)
Dynamics 365 Business Central Essential D365 TROUBLESHOOT (non-default)
D365 SECURITY (non-default)
USER N A M E
T H E T Y P E O F SUB SC RIP T IO N P L A N
A SSIGN ED TO T H E GIVEN USER USER GRO UP S

INTERNALADMIN D365 INTERNAL ADMIN


D365 TROUBLESHOOT
Internal Administrator (Microsoft 365 Global administrator D365 BACKUP/RESTORE
role) D365 SECURITY (non-default)

TEAMMEMBER D365 TEAM MEMBER


D365 TROUBLESHOOT (non-default)
Dynamics 365 for Team Members D365 SECURITY (non-default)

DEVICE D365 FULL ACCESS


EXTEND. MGT. - ADMIN (non-default)
Dynamics 365 Business Central Device D365 BUS PREMIUM (non-default)*
D365 TROUBLESHOOT (non-default)

D365 SECURITY (non-default)

*) Please note: usage need to be according to terms in


Licensing Guide

DELEGATEDADMIN EXTEND. MGT. - ADMIN


D365 FULL ACCESS
Delegated Admin agent - Partner D365 RAPIDSTART
Delegated Helpdesk agent - Partner D365 BACKUP/RESTORE
D365 TROUBLESHOOT
D365 SECURITY (non-default)

TIP
For more information about how to choose a user experience, see Changing Which Features are Displayed.

Assigning the Premium plan to test users


Depending on how you are running your Docker sandbox, you assign the experience in different ways.
Azure VMs
If you use https://aka.ms/bcsandbox to create your Dynamics 365 Business Central Sandbox Container Azure
VM, the Azure Resource Manager template has two fields; Assign Premium Plan and Create Test Users ,
which by default are set to Yes .
Assign Premium Plan specifies whether or not your admin user should be assigned a Premium plan. Create
Test Users specifies whether or not you want the setup to include test users.
BCContainerHelper
If you are using New-BCContainer to create your Dynamics 365 Business Central Sandbox container, you must
make sure that you are using version 0.2.8.3 or later.
Use the switch assignPremiumPlan on New-BCContainer like this:

New-BCContainer -accept_eula -updateHosts -containerName test -artifactUrl (Get-BCArtifactUrl -country us) -


assignPremiumPlan

This assigns the Premium plan to your default admin user. Internally this just adds a record to the User Plan
table.
To create the test users, you must call the Setup-BCContainerTestUsers method:

Setup-BCContainerTestUsers containerName test -tenant default -password $securePassword

specifying the container and the password that you want to use for the new users.
Internally, the Setup-BCContainerTestUsers downloads an app which exposes an API, publishes and installs the
app, and then invokes the CreateTestUsers API with the password needed. After this, the app is uninstalled and
unpublished.
If you want to see code behind the app, it is available here.
Docker run
If you are using Docker run to run your containers, you have a little more work to do.
First of all, you must override the SetupNavUsers.ps1 by sharing a local folder to c:\run\my in the container and
place a file called SetupNavUsers.ps1 in that folder with the following content:

# Invoke default behavior


. (Join-Path $runPath $MyInvocation.MyCommand.Name)

Get-NavServerUser -serverInstance $ServerInstance -tenant default |? LicenseType -eq "FullUser" | ForEach-


Object {
$UserId = $_.UserSecurityId
Write-Host "Assign Premium plan for $($_.Username)"
Invoke-Sqlcmd -ErrorAction Ignore -ServerInstance 'localhost\SQLEXPRESS' -Query "USE [$TenantId]
INSERT INTO [dbo].[User Plan`$63ca2fa4-4f03-4f2b-a480-172fef340d3f] ([Plan ID],[User Security ID])
VALUES ('{8e9002c0-a1d8-4465-b952-817d2948e6e2}','$userId')"
}

This will assign the Premium plan to the admin user in the database.

TIP
To set up test users, you can clone the createtestusers repository and modify the code to create the users on the
oninstall trigger with the password that you want.

See Also
Programming in AL
Sandbox Environments for Dynamics 365 Business Central Development
Container Sandbox
Changing Which Features are Displayed
Production and Sandbox Environments
App Identity
2/6/2023 • 4 minutes to read • Edit Online

Apps built using AL extend the functionality of Business Central. The app.json file is, together with the
launch.json file, automatically generated when you create a new AL project. The app.json file contains
information about the app that you are building, such as publisher information and specifies the minimum
version of base application objects that the extension is built on. Often the app.json file is referred to as the
manifest. The app.json file contains numerous project settings, but a few of them constitutes the actual identity
of the app that you are creating.

NOTE
With Business Central 2021 release wave 2, name and publisher are no longer considered part of the app identity and
can therefore be changed to reflect branding or acquisition, for example. If the name and/or publisher information is
changed, the version must also be incremented. If you are using workspaces with multiple projects and change the
name or publisher of an extension in the workspace, the dependencies in the app.json file must be updated with the
new name and publisher or you may encounter issues with reference resolution. For more information, see Working with
Multiple Projects and Project References.

IMPORTANT
In cases where the Application app is substituted with another application app, the name is still used as identification. For
more information, see The Microsoft_Application.app File.

SET T IN G EXA M P L E DESC RIP T IO N

id "id": "ef4dabfc-1de7-4d90-b948- The id , also known as the app ID.


4a9c2933d794" This is a GUID which is auto-generated
when the project is created. The app ID
is also bound to how tables are named
in Business Central and how the
identity of an application is computed.
Changing the app ID may have severe
consequences, such as the app not
functioning properly, or data not being
available.

version "version": "1.0.0.0" The version is used to distinguish


between different iterations of your
app. The version number should
increase as you make changes to your
app.

For more settings, see JSON Files.


For apps published in the Global scope, see Publish NAVApp, such as AppSource and 1st party applications, the
id and the version identify a unique application package. The Business Central service uses these tuples to
refer to apps in different flows. To prevent issues, it is required that the id remains the same after an app is
uploaded to the Business Central service, and that you only increment the version .
For apps published in the Tenant scope, see Publish NAVApp, such as per-tenant customizations, in addition to
the id and version , the tenant ID is also used to uniquely identify an app.

When is it okay to change the ID of an app?


The id of an app is automatically generated by the AL Language extension when you create a new app or if
you use the AL: Generate manifest command.
If you have copied the app or the manifest from another app, you must change the id before publishing it to
the online service as a per-tenant extension or AppSource app.
After the app has been published, you should only change the id if you intend to use the code base to develop
a new app. You will not be able to upgrade from the app with the old id to the app with the new id because
the system does not have knowledge about the correspondence.
If you have published your app as a per-tenant extension, but you are now considering publishing it to
AppSource, you must assign a new id to the AppSource app, as well as ensure that it follows all the technical
requirements for publishing to AppSource. For more information, see Moving Between Extension Scopes.
It is recommended to use a different id for the app that you publish from Visual Studio Code or to the
container. Once you are satisfied with the quality of your app and ready to publish it to AppSource, it is
recommended to use a different id . If you do not follow this approach, the app that you have published from
Visual Studio Code to a developer sandbox will be automatically unpublished if another user tries to install the
AppSource app. For more information, see Moving Between Extension Scopes.

When is it okay to change the name of an app?


If you are targeting only Business Central 2021 release wave 2 or later, the name of an app can be changed at
any point also after it has been published. If the name is changed, the version must be incremented as well.
If you are targeting versions of Business Central prior to 2021 release wave 2, then the name of an app cannot
be changed after it has been published.

When is it okay to change the publisher of an app?


If you are targeting only Business Central 2021 release wave 2 or later, the publisher of an app can be changed
at any point also after it is published. If the publisher is changed, the version must be incremented as well.
If you are targeting versions of Business Central prior to 2021 release wave 2, then the publisher of an app
cannot be changed after it has been published.

When is it okay to change the version of an app?


The version must be incremented any time a new version of your app is uploaded to AppSource or as a per-
tenant extension. While developing it in Visual Studio Code, you can keep using the same version and iterate on
your code.

NOTE
In a Visual Studio Code workspace an app's name , publisher , and version are part of identifying a project and a
project dependency. Therefore, if any of these properties change, it is recommended that you reload the workspace.

See Also
JSON Files
Publish NAVApp
Working with Multiple Projects and Project References
Choosing Runtime Version in AL
2/6/2023 • 2 minutes to read • Edit Online

The capabilities and features of AL for Business Central are determined by the runtime version. The runtime
version can be specified in the app.json file for a project. It is expressed with the following syntax, for example:
"runtime": "7.0" . Specifying the runtime version is mostly interesting for scenarios where you develop for on-
prem or a mix of on-prem and SaaS. For SaaS only development, you will most likely be interested in using the
current runtime. If the runtime setting is not specified, the compiler will detect the runtime that matches the
server.
The runtime version specified in the app.json file determines which runtime the project is targeting. A project
can be published to the server with an earlier or with the same runtime version as the server.

Currently available runtime versions


The available options for setting the runtime in AL are:

RUN T IM E VERSIO N SH IP P ED W IT H IN T ERN A L VERSIO N

1.0 Business Central April 2018 Release 12.0

2.0 Business Central Fall '18 Release 13.0

3.0 Business Central Spring '19 Release 14.0

4.0 Business Central 2019 release wave 2 15.0

5.0 Business Central 2020 release wave 1 16.0

6.0 Business Central 2020 release wave 2 17.0

6.1 Business Central 2020 release wave 2 17.1


update 1

6.2 Business Central 2020 release wave 2 17.2


update 2

6.3 Business Central 2020 release wave 2 17.3


update 3

6.4 Business Central 2020 release wave 2 17.4


update 4

7.0 Business Central 2021 release wave 1 18.0

7.1 Business Central 2021 release wave 1 18.1


update 1

7.2 Business Central 2021 release wave 1 18.2


update 2
RUN T IM E VERSIO N SH IP P ED W IT H IN T ERN A L VERSIO N

8.0 Business Central 2021 release wave 2 19.0

9.0 Business Central 2022 release wave 1 20.0

9.1 Business Central 2022 release wave 1 20.1


update 1

9.2 Business Central 2022 release wave 1 20.4


update 2

10.0 Business Central 2022 release wave 2 21.0

Setting the runtime version


Selecting the runtime depends on the circumstances. If you, for example, have customers that run on older
versions, you should set the runtime to be the minimum version that works to ensure compatibility. This will
prevent you from inadvertently using features that are not supported on the older server.
If an earlier runtime is picked, it can be good idea to have a daily or weekly build that tests the extension against
the latest version of the runtime. Testing against the latest runtime can detect new diagnostics, such as warnings
or errors, that are introduced in the compiler or changes in the platform runtime. Though it may not be possible
to refactor code for a future runtime, while using an older runtime, staying on top of these changes may help
making design decisions early on.

See Also
JSON Files
FAQ about Library and Dependency Apps in
Business Central
2/6/2023 • 2 minutes to read • Edit Online

This section contains answers to frequently asked questions about library apps and dependency apps in
Business Central.

What is a library app?


A library app contains common code that other apps depend on. If you're going to have multiple AppSource
apps that all share common code, such as licensing, registration, and so on, you can put that common code into
a library app and have the AppSource apps depend on the library app.

How does the library app get installed to a tenant?


A library app doesn't appear on AppSource. It only lives in Business Central. Our service is built to install the
library apps behind the scenes. Here's how it works. Customers find an app they want to install on AppSource.
That customer doesn't know the app even has library app(s). When they select to install the app, our service
looks into that apps json/manifest to see if it first needs to install any library/dependency apps it may depend
on. If so, it installs them first before installing the main AppSource app.

What is a dependency app?


A dependency app isn’t much different from a library app. A dependency app does have its own offer on
AppSource. For example, you might have AppSource “App A” that serves a purpose on its own and is listed on
AppSource. You then also have “App B” as its own offer on AppSource but it does depend on code within “App A”
and needs “App A” to be installed before it can be installed. This is really the only difference though. Behind the
scenes, library and dependency apps behave the same when it comes to walking that dependency chain and
auto installing any app the top-level app depends on.

Can I have multiple library apps for my AppSource app?


Yes. Just make sure you list all library apps as dependencies within the AppSource app json file/manifest.

When I get the latest updated version of my app, why don't I get the
updated library/dependency apps that my AppSource app depends
on?
Libraries are updated only when the new version of your app requires a higher version than the version
currently installed in your environment. If you want your library app to be automatically updated when your
AppSource app is updated, you must increase the minimum version required in the manifest (app.json) of your
AppSource app.
You can also uninstall and reinstall the library/dependency app to have it updated.

What are the validation requirements for library apps


Library apps only get validated technically, but don't go through any type of marketing validation. The technical
requirements are described here.
See also
FAQ about Managing and Submitting your Business Central Offer
FAQ about Updating your Business Central App
Update Lifecycle for AppSource Apps FAQ
The Lifecycle of Apps and Extensions for Business Central
Adding data for Extensions
2/6/2023 • 2 minutes to read • Edit Online

For your extension to run properly, configuration and starting data such as permission sets and table data may
be needed. An extension can include the following types of data that can be imported for the tenant during the
installation of the extension.
Permission sets
Web services
Starting table data
Custom report layouts
The data must be exported into files to be included in the extension. To use the export functions you must use a
container sandbox environment for Dynamics 365 Business Central. For more information, see Get started with
the Container Sandbox Development Environment.

To add permission sets


1. Open the Business Central Development Shell.
2. Export the relevant permission set using the Export-NAVAppPermissionSet cmdlet to export the permission
set to a file. For example, the following command exports the BASIC permission set.
Export-NAVAppPermissionSet -ServerInstance DynamicsNAV160 -Path '.\PermissionSet.xml' -PermissionSetId
BASIC

NOTE
Export each permission set to a separate XML file.

3. Add the exported permission set files to the Visual Studio Code project that contains your extension.

WARNING
If you do not include a permission set with your extension, only users with the SUPER permission set will be able
to use the extension.

IMPORTANT
With the latest version of Dynamics 365 Business Central permissions are no longer defined as data in the
application database. Permissions that can be created by using AL objects are called system permissions. For more
information, see Entitlements and Permission Sets Overview.

To add web services


1. Open the Business Central Development Shell.
2. Export the relevant web service using the Export-NAVAppTenantWebService cmdlet to export the web
service to a file. The following command exports the Customer Card page.
Export-NAVAppTenantWebService -ServerInstance DynamicsNAV160 -Path TenantWebService.xml -ServiceName
Customer -ObjectType Page -ObjectId 21

NOTE
Export each web service to a separate XML file.

3. Add the exported web services files to the Visual Studio Code project that contains your extension. An
exported web service XML file looks like the following:

<?xml version="1.0" encoding="utf-8"?>


<ExportedData>
<TenantWebServiceCollection>
<TenantWebService>
<ObjectType>Page</ObjectType>
<ObjectID>21</ObjectID>
<ServiceName>Customer</ServiceName>
<Published>true</Published>
</TenantWebService>
</TenantWebServiceCollection>
</ExportedData>

You may also merge multiple XML files into one:

<?xml version="1.0" encoding="utf-8"?>


<ExportedData>
<TenantWebServiceCollection>
<TenantWebService>
<ObjectType>Page</ObjectType>
<ObjectID>21</ObjectID>
<ServiceName>Customer</ServiceName>
<Published>true</Published>
</TenantWebService>
<TenantWebService>
<ObjectType>Page</ObjectType>
<ObjectID>26</ObjectID>
<ServiceName>Vendor</ServiceName>
<Published>true</Published>
</TenantWebService>
</TenantWebServiceCollection>
</ExportedData>

To add table data


1. Open the Business Central Development Shell.
2. Export the relevant data using the Export-NAVAppTableData cmdlet to export the data to a file. This
includes setting the path to a folder where you want the .navxdata file created. A data file in the format of
TAB<TABLEID>.navxdata will be created. (Example: TAB10000.navxdata).

Export-NAVAppTableData -ServerInstance DynamicsNAV160 -Path 'C:\NAVAppTableData' -TableId 10000

NOTE
Export the data for each table to a separate XML file.

3. Add the exported table data files to the Visual Studio Code project that contains your extension.
4. Call the procedure in a Codeunit with the Subtype property Install or Upgrade and specify the table ID
in the NavApp.LoadPackageData procedure as shown in the following example.

codeunit 50100 MyExtensionUpgrade


{
Subtype = Upgrade;
trigger OnUpgradePerDatabase()
begin
NavApp.LoadPackageData(50100);
end;
}

WARNING
An extension can only include table data for new tables that are added as part of the extension.

To add custom report layouts


1. Open the Business Central Development Shell.
2. Export the relevant report layouts using the Export-NAVAppReportLayout cmdlet to export to a file:
Export-NAVAppReportLayout -ServerInstance DynamicsNAV160 -Path .\ReportLayout.xml -LayoutId 1

NOTE
Export each custom report layout to a separate XML file.

3. Add the exported custom report files to the Visual Studio Code project that contains your extension.

See Also
Developing Extensions in AL
Converting Extensions V1 to Extensions V2
Writing Extension Install Code
The Txt2Al Conversion Tool
2/6/2023 • 5 minutes to read • Edit Online

DEPRECATED WITH Starting with Business Central 2022 Release Wave 2 (v21) this tool is no longer
available.

The Txt2Al conversion tool allows you to take C/AL objects, which were created in Dynamics NAV or Business
Central Spring 2019 (version 14), and convert them into the new .al format. The .al format is used when
developing extensions for Dynamics 365 Business Central. Converting the objects consists of following two
steps:
1. Exporting the objects from C/SIDE in a cleaned .txt format.
2. Converting the objects to the new syntax.

Where to get the Txt2Al conversion tool


The Txt2Al conversion tool (txt2al.exe) is only available with version 14, which is the last version to support C/AL.
Use this version no matter what later version you may eventually be upgrading to. The AL objects created by the
tool will be compatible with later versions.
You find the txt2al.exe on the installation media (DVD) in the "DVD\RoleTailoredClient\program files\Microsoft
Dynamics NAV\140\RoleTailored Client" folder. Or, it's installed locally with Dynamics NAV Development
Environment, for example, in the "C:\Program Files (x86)\Microsoft Dynamics 365 Business
Central\140\RoleTailored Client" folder.

Using the Txt2Al conversion tool


To run the Txt2Al conversion tool, follow the steps outlined below.
1. Start with a clean Dynamics NAV database and compile the database.
It's ver y important that you compile the database to get the right result in the next step.
2. Make an export of all the baseline objects in the command line using the following syntax:
finsql.exe Command=ExportToNewSyntax, File=<filename.txt>, Database="<databasename>", ServerName=
<servername> ,Filter=Type=table;ID=<tableID>
The following example exports the table 225 from the Demo Database NAV (13-0) database:
finsql.exe Command=ExportToNewSyntax, File=exportedBaselineObjects.txt, Database="Demo Database NAV (13-
0)", ServerName=.\NAVDEMO ,Filter=Type=table;ID=225
3. Import your solution using the import option in C/SIDE and compile the database.
It's ver y important that you compile the database to get the right result in the next step.
4. Export all new and/or modified objects using the following syntax:
finsql.exe Command=ExportToNewSyntax, File=<filename.txt>, Database="<databasename>", ServerName=
<servername> ,Filter=Type=table;ID=<tableID>
The following example exports the table 231 from the Demo Database NAV (13-0) database:
finsql.exe Command=ExportToNewSyntax, File=exportedNewModifiedObjects.txt, Database="Demo Database NAV
(13-0)", ServerName=.\NAVDEMO ,Filter=Type=table;ID=231
5. Run the Set-ObjectPropertiesFromMenuSuite cmdlet, which will convert MenuSuite information on pages
and reports in the generated AL objects to enable them for search. For more information, see Making Pages
and Reports Searchable in the Web client
6. Create .delta files using the Compare-NAVApplicationObject PowerShell script. For more information, see
Generating DELTA Files.
7. Go to the \Program Files(x86)\Microsoft Dynamics 365 Business Central\140\RoleTailored Client folder and
locate the txt2al.exe converter tool.
8. Run the tool from the command line using the following syntax:
txt2al --source --target --rename --type --extensionStartId --injectDotNetAddIns --dotNetAddInsPackage --
dotNetTypePrefix --translationFormat --addLegacyTranslationInfo

Parameters
PA RA M ET ER DESC RIP T IO N

--source=Path Required. The path of the directory containing the .delta files.

--target=Path Required. The path of the directory into which the converted
AL files will be placed.

--rename Rename the output files to prevent clashes with the source
.txt files.

--type=ObjectType The type of object to convert. Allowed values: Codeunit,


Table, Page, Report, Query, XmlPort

--extensionStartId The starting numeric ID of the extension objects (Default:


70000000). It will be incremented by 1 for each extension
object.

--stacktrace Display the stack trace of exceptions raised during the


conversion.

--help Show help screen.

--injectDotNetAddIns Inject the definition of standard .NET add-ins in the resulting


.NET package. The standard .NET add-ins are a set of add-ins
that are embedded into the platform.

--dotNetAddInsPackage=Path Specify the path to an AL file that contains a definition for a


.NET package containing .NET type declarations that should
be included in the .NET package definition that's produced
by the conversion. This parameter should be used to inject a
custom set of .NET control add-in declarations. The file
should contain something similar to the example shown
below.

--multithreaded Run using multiple threads. This parameter improves


performance but results in non-repeatable extension
numbers and .xlf content.

--dotNetTypePrefix Specify a prefix to be used for all .NET type aliases created
during the conversion.

--translationFormat=ObjectType Specify the format to use when generating translation files.


The allowed values are: Xliff, Lcg.
PA RA M ET ER DESC RIP T IO N

--addLegacyTranslationInfo Add information to the translation file that can be used to


migrate existing translations/translated resources. During
conversion, XLIFF files from all the ML properties in the app
are extracted. If this switch is set, a comment is added in the
generated XLIFF that specifies what the ID of the translation
item would be in C/SIDE. This acts as a mapping that allows
you to convert existing translation resources for your app.

--runtime Specify the target runtime for the converted AL. The default
is the latest supported runtime. The string should be in a
format similar to major.minor .

--objectFileNamePattern Specify the pattern for naming AL files that contain AL


objects by using the following placeholders: {name} -
object name, {type} - object type, {id} - object ID. This
parameter only takes effect if --rename is specified. The
default is {name}.{type} .

--extensionObjectFileNamePattern Specify the pattern for naming AL files containing AL


extension objects by using the following placeholders:
{name} - extension object name, {type} - extension
object type, {id} - object ID, {targetName} - the name
of the object being extended, {targetId} - the ID of the
object being extended. This parameter only takes effect if
--rename is specified. The default is
{name}.{type}-{targetName} .

--format Format the converted AL code using the standard formatter.

--dataClassificationDefaulting Specify the DataClassification property for all table fields that
don't have it specified. For more information, see
DataClassification Property.

--tableDataOnly For table objects, specifies to convert only the table and field
definitions, including properties. Methods and trigger code
isn't included. Note: This parameter was first introduced in
Business Central version 14.2 (cumulative update 11) and
Business Central version 15.5.

NOTE
It's recommended to only use the conversion tool for export. Importing objects that have been exported can damage
your application.

TIP
You can use the Dynamics NAV Development Shell cmdlet Export-NAVApplicationObject with the
-ExportToNewSyntax flag set instead of using finsql. From the command prompt in the Dynamics NAV Development
Shell, run Get-Help Export-NAVApplicationObject -full to see the full syntax.

See Also
Developing Extensions
AL Development Environment
Page Extension Object
Report Object
Page Properties
Viewing Table Data
2/6/2023 • 2 minutes to read • Edit Online

For developers, administrators, and support personnel, it can be useful to inspect table data in the tenant
database, particularly when debugging or troubleshooting. To support this need, you can view table objects in
the Web client. This lets you see the data in all rows and columns of a specific table, including any columns that
are added by table extensions.
In a production environment, administrators and support can view a table directly from the Web client.
From the Business Central administration center, you can launch a list of all tables, sorted by storage size.
For more information, see Storage usage by environment.
In a development environment, in addition to viewing a table directly from the Web client, developers can
view a table automatically when they publish/debug an AL project from Visual Studio Code.

NOTE
The table appears as read-only in the client, so modifications, insertions, and deletions cannot be made.

IMPORTANT
Data in the tables can be sensitive. Make sure that you follow your organization's guidelines for handling such data.

Required permissions
Whether viewing the table directly from the client or from Visual Studio Code, your Dynamics 365 user account
must have the following permissions:
Read permission on the table that you want to view.
Execution permission (direct) on the System object 1350 Run table .
Any end-user that is assigned these permissions will be able to view that table in the browser.
For information about assigning permissions, see Manage Users and Permissions.

View a table object directly from the client


To view a table, you add the table=<TableID> parameter to the client's address (URL), replacing <TableID> with
the ID of the table that you want to view.
For example, if your URL starts with https://businesscentral.dynamics.com , then to view table 18 Customer in
your current company, you could use the following URL:

https://businesscentral.dynamics.com/?table=18

Or, for a specific company, such as "CRONUS Inc.":


https://businesscentral.dynamics.com/?company=CRONUS%20Inc.&table=18

Note the use of & when table=<TableID> isn't located directly after the domain name.

View a table object from an AL project in Visual Studio Code


You can configure an AL project to view a table when you publish or debug the project (pressing F5 or
Ctrl+F5 ).
In the launch.json file for the project, set the "startupObjectType" parameter to "table" and the
"startupObjectId" parameter to the ID of the table. For example:

{
"version": "1.0.0",
"configurations": [
{
"type": "al",
"request": "launch",
"name": "Publish to Microsoft cloud sandbox",
"serverInstance": "dynamics",
"startupObjectType": "Table"
"startupObjectId": 18
}
]
}

For more information about the launch.json file, see Launch.json file.

Constraints
You cannot view virtual tables or the following system tables:

ID NAME

2000000170 Configuration Package File

2000000173 Data Sensitivity

2000000100 Debugger Breakpoint

2000000103 Debugger Watch

2000000130 Device

2000000114 Document Service

2000000190 Entitlement Set

2000000191 Entitlement

2000000180 MediaSet

2000000181 Media
ID NAME

2000000195 Membership Entitlement

2000000162 Nav App Capabilities

2000000152 Nav App Data Archive

2000000161 Application Dependency (*Nav App Dependencies)

2000000150 Application Object Metadata (*Nav App Object Metadata)

2000000163 Nav App Object Prerequisites

2000000142 Application Resource (*Nav App Resource)

2000000151 Installed Application (*Nav App TenantApp)

2000000160 Published Application (*Nav App)

2000000071 Object Metadata

2000000079 Object Tracking

2000000001 Object

2000000198 Page Documentation

2000000186 Profile Page Metadata

2000000082 Report Layout

2000000065 Send To Program

2000000112 Server Instance

2000000066 Style Sheet

2000000197 Token Cache

2000000081 Upgrade Blob Storage

2000000121 User Property

2000000076 Web Service

2000000194 Webhook Notification

2000000199 Webhook Subscription


NOTE
The tables marked with * in the table above changed names with Business Central 2020 release wave 1. For more
information, see Deprecated Tables.

See Also
Developing Extensions
Deprecated Tables
Managing Capacity
Inspecting and Troubleshooting Pages
2/6/2023 • 6 minutes to read • Edit Online

The Business Central Web client includes a page inspection feature that lets you get details about a page. Page
inspection provides insight into the page design, the different elements that form the page, and the source
behind the data it displays. Page inspection helps you:
Learn the data model behind a page.
Discover pages and parts that can be reused in your application design.
Troubleshoot data issues without having to do tasks like copying the production database, viewing the entire
source table, or digging into SQL.
Debug the application, complementing Designer.

Working with Page Inspection


You start page inspection from the Help & Suppor t page. Choose the question mark in the top-right corner,
choose Help & Suppor t , and then choose Inspect pages and data . Or, you can just use the keyboard
shortcut Ctrl+Alt+F1 .
The Page inspection pane opens on the side. The following figure illustrates the Page Inspection pane on the
Sales Order page.

When the Page Inspection pane first opens, it shows information that pertains to the main page object.
Use the keyboard or pointing device to move focus to different elements on the page. When you select a FactBox
or a part on the main page, a border will highlight the area. The Page Inspection pane then shows information
about the selected element. For example, the previous figure shows information about the list part in the Sales
Order page.
As you navigate to other pages in the application, the Page Inspection pane will automatically update with
page information as you move along.
What Page Inspection Shows
The page inspection pane shows the information for the main page or page part, including:
The page's source table (if any) and fields.
Extensions that affect the page.
Current filters applied to the page.
The following sections describe details about what is shown.

NOTE
If you do not see all details described below, you might not have the required permissions. For more information, see
Controlling Access to Page Inspection Details.

TIP
To copy the values of a field or entity under one of the tabs to the clip board, select the field or entity and press Ctrl+C.

Page
Table
Table Fields
Extensions
Page Filters

The Page field shows information about the main page or a selected (highlighted) subpage in a part. The field
shows the following information:
The name, as specified by its Name property
The ID as specified by the ID property.
The type, as specified by the PageType property.
Elements shown with limited information
Role Center pages
If a page has the type Role Center, the Table field doesn't appear. Because the Role Center consists of
several parts, there's no more information shown. To see more details, select the different parts that make
up the Role Center.
Report request pages and previews
If you open a report request page or preview for inspection, the only information shown in the Page
Inspection pane is the report's name and ID.

TIP
From the Business Central client, you can export report results as raw data to a Microsoft Excel file. The file
contains all columns of the dataset, but without the layout applied. Use the file to help validate that the report
returns the expected data, and to ensure that the report layout controls match the dataset value types. To export
a report, run the report and select the Send to > Microsoft Excel Document (data only) on the request
page. For more information, see Working with Reports - Send to Excel.

System parts, such as Links or Notes, and parts containing charts.


See Also
AL Development Environment
Page Extension Object
Actions Overview
Adding Pages and Reports to Search
Personalizing Your Workspace
Using Designer
Programming in AL
2/6/2023 • 2 minutes to read • Edit Online

AL is the programming language that is used for manipulating data such as retrieving, inserting, and modifying
records in a Dynamics 365 Business Central database. It controls the execution of the various application objects,
such as pages, reports, or codeunits.
With AL, you can create business rules to ensure that the data, which is stored in the database is meaningful and
consistent with the way customers do business. Through AL programming, you can:
Add new data or transfer data from one table to another, for example, from a journal table to a ledger table.
Combine data from multiple tables into one report or display it on one page.

Where to write AL code


Almost every object in Dynamics 365 Business Central contains triggers where you can add your AL code.
Triggers exist for the following objects:
Tables and table extensions
Table fields
Pages and page extensions
Reports
Data items
XMLports
Queries
You can initiate the execution of your AL code from the following ways:
Actions
Any object that has an instantiation of the object that contains AL code. An example of an instantiation is a
variable declaration.

NOTE
If the AL code is in a local method, then you cannot run it from another object.

Variable declarations
Variables in AL are declared using the var keyword, and the syntax looks like this:

var
myInt: Integer;

If you have multiple variables of the same type, these can be declared in one line, such as:

var
myInt, nextInt, thirdInt : Integer;
isValid, doCheck : Boolean;
The protected keyword can be used to make variables accessible between tables and table extensions and
between pages and page extensions. For more information, see Protected Variables.

Guidelines for placing AL code


We recommend the following guidelines for AL code:
In general, write the code in codeunits instead of on the object on which it operates. This promotes a
clean design and provides the ability to reuse code. It also helps enforce security. For example, typically
users don't have direct access to tables that contain sensitive data, such as the General Ledger Entr y
table, nor do they have permission to modify objects. If you put the code that operates on the general
ledger in a codeunit, give the codeunit access to the table, and give the user permission to run that
codeunit. This way, security of the table won't be compromised and the user will be able to access the
table.
If you must put code on an object instead of in a codeunit, then put the code as close as possible to the
object on which it operates. For example, put code that modifies records in the triggers of the table fields.

Reusing code
Reusing code makes developing applications both faster and easier. More importantly, if you organize your AL
code as suggested, your applications will be less prone to errors. By centralizing the code, you won't
unintentionally create inconsistencies by performing the same calculation in many places, for example, in
several triggers that have the same table field as their source expression. If you have to change the code, you
could either forget about some of these triggers or make a mistake when you modify one of them.

See Also
Simple Statements
Control Statements
Methods
System-Defined Variables
Developing Extensions
Get Started with AL
FAQ for Developing in AL
2/6/2023 • 2 minutes to read • Edit Online

This topic contains a number of frequently asked questions and answers to these questions.

How do I get started?


For an overview of developing apps for Dynamics 365 Business Central, see aka.ms/GetStartedWithApps
Next, follow the Get Started with AL to set up the tools.

Which version of the AL Language extension should I use?


For Dynamics 365 Business Central cloud sandboxes you must use the AL Language extension available in the
Visual Studio Code Marketplace.
For the latest Developer Preview releases you must use the AL Language extension that is available in the next
major artifact through the "Ready! for Dynamics 365 Business Central" program on Microsoft Collaborate.

How do I enable the debugger?


To read about enabling debugging in AL, see here Debugging. To read about snapshot debugging, see Snapshot
Debugging.

Where do I find help regarding AppSource validation and submission?


When submitting an app for AppSource, you must make sure that it validates against the Technical Validation
Checklist. For frequently asked questions, see Technical Validation Checklist FAQ.

What constitutes the identity of an app?


To read about app identity and why it is important to keep certain settings for an app unchanged, see App
Identity.

File APIs are not available in Extensions V2. What do I do?


Code that relies on temporary files must be rewritten to rely on InStream and OutStream types. Code that relies
on permanent files must be rewritten to use another form of permanent storage.

DotNet types are not available in Extensions V2. What now?


For cloud solutions .NET interop is not available due to safety issues in running arbitrary .NET code on cloud
servers.
With the AL Language extension, you can find AL types that replace the most typical usages of .NET like HTTP,
JSON, XML, StringBuilder, Dictionaries, and Lists. Many .NET usages can be replaced directly by the AL types
resulting in much cleaner code. For more information, see HTTP, JSON, TextBuilder, and XML API Overview.
For things that are not possible to achieve in AL code, the recommendation is to use Azure Functions to host the
DLL or C# code previously embedded and call that service from AL.
Extensions published from Visual Studio Code or created using
Designer have disappeared from a sandbox environment. Why?
Extensions that have been published to a sandbox environment from Visual Studio Code or created using
Designer are removed when the sandbox environment is updated or relocated within our service. However, the
data of an app is not removed, so you only have to re-publish and install the app to make it available.
If you have per-tenant extensions (PTEs) installed that depend on extensions published from Visual Studio Code,
the per-tenant extensions will be removed too.
For more information, see Sandbox Environments.

Can I create something similar to Menusuites?


In the AL Language extension, the concept of Menusuites is not supported. The two primary purposes of
Menusuites are:
Making pages searchable
Making pages accessible through a navigation structure
The first purpose can be achieved in Extensions by using the new properties added to Pages and Reports. For
more information, see Adding Pages and Reports to Search.
The second purpose can be achieved by extending the Navigation Pane page and/or by adding Actions to other
existing pages that can serve as a navigation starting point. For more information, see Adding Menus to the
Navigation Pane.

How do I upgrade Extensions V1 to Extensions V2?


For information on upgrading, see the following topics: Upgrading Extensions v2 and Converting from
Extensions v1 to Extensions v2.

See Also
Get Started with AL
Keyboard Shortcuts
AL Development Environment
System-Defined Variables
2/6/2023 • 2 minutes to read • Edit Online

Dynamics 365 Business Central automatically declares and initializes several variables that you can use when
you develop applications. The following table describes the system-defined variables.

SY ST EM - DEF IN ED VA RIA B L E DESC RIP T IO N

Rec When a record is modified, this variable specifies the current


record, including the changes that are made.

xRec When a record is modified, this variable specifies the original


values of the record before the changes.

CurrPage This variable specifies the current page.

CurrReport This variable specifies the current report.

RequestOptionsPage This variable specifies the request options page for the
current report.

CurrFieldNo This variable specifies the field number of the current field in
the current table. Retained for compatibility reasons.

Using Rec and xRec


The following example shows how to use the Rec and xRec pair of records.
In an application, data is stored in two tables, a header table and a line table. The header table contains general
information about, for example, sales orders, while the line table contains the specific order lines. The page that
you use to enter information into the header table has fields that contain the customer’s address. These fields
are related to the Customer table, and can be filled by using a lookup method in the field that establishes the
relationship. In the header table, only the customer number is stored, and the other fields that have customer
information, such as name and address, are retrieved from the Customer table when the Customer No. field
is validated.
In some situations, the user should be able to change the customer number, and in other situations the user
shouldn't be able to change it. For example, if the order has already been shipped, the user shouldn't be able to
change the customer number. If there's an incorrect number on an order that hasn't been processed completely,
the user should be able to correct the error.
You could use the Rec and xRec variables to design your application in the following way:
When validating the customer number field, check whether the order has shipped.
If the order has shipped, compare the customer number fields in the Rec and xRec records. If they differ, reject
the change.

Using CurrPage
You can access the controls of the page through the CurrPage variable and set the dynamic properties of the
page and its controls. The CurrPage.Editable variable reflects the runtime value of the Editable property, which
can be changed at design-time, programmatically, or by the user when switching view modes on a page. The
CurrPage.Update([SaveRecord]) variable can be used to save the current record and then update the controls on
the page. When the View mode on a page is false , then the Edit, New, and Delete modes are true .

Using CurrReport
You can access properties of a report through the CurrReport variable and set them dynamically. For example,
by using CurrReport.Preview, you can determine if the report is being run in preview mode.

Using RequestOptionsPage
You can access properties of the request page through the RequestOptionsPage variable and set them
dynamically.

See Also
AL Method Reference
Properties
AL Simple Statements
2/6/2023 • 5 minutes to read • Edit Online

AL simple statements are single-line statements that are executed sequentially and don't alter the flow of code
execution. This article explains some of the simple statements in AL.

Assignment statements
Assignment statements assign a value to a variable. The value that you assign to the variable is an AL
expression. It can be a constant or a variable, or it can consist of multiple elements of AL expressions. If you use
a method call as the value to assign to a variable in an assignment statement, then the value that is assigned is
the return value of the method.
You use the ":=" operator for assignment statements.
Example
The following example assigns a constant integer value to a variable that you've defined.

Count := 1;

Example
The following example assigns a value that consists of a constant, an operator, and a variable.

Amount := 2 * Price;

Example
The following example assigns the return value of the Open Method (File) to a Boolean variable that you've
defined.

NOTE
This method is supported only in Business Central on-premises.

OK := TestFile.Open('C:\temp\simple.xml');

The return value of the Open method is optional. If you don't handle the return value in your code, then a run-
time error occurs when a method returns false . The following example causes a run-time error if the file
C:\temp\simple.xml can't be opened.

TestFile.Open('C:\temp\simple.xml');

You can handle the return value by using an if-then statement.


if TestFile.Open('C:\temp\simple.xml') then begin
// continue running
else
Error(Text001);

Example
If you want to perform arithmetic operations on a variable and then assign the result to the same variable, you
can use the following syntax.

Counter := 0;

// you can use this syntax

// for addition
Counter += 1;
// for subtraction
Counter -= 1;
// for multiplication
Counter *= 1:
// for division
Counter /= 1;

// instead of
Counter := Counter + 1;

The following example shows how to use this syntax on variables of the Text Data Type.

String := "Hello ";


String += "World";

Method statements
You use method statements to run either built-in system methods or user-defined (custom) methods. Method
calls may include parameters, which are passed to the method. For more information, see Calling Methods.

AssertError statements
You use AssertError statements in test methods to test how your application behaves under failing conditions.
The AssertError keyword specifies that an error is expected at run time in the statement that follows the
AssertError keyword.

If a simple or compound statement that follows the AssertError keyword causes an error, then execution
successfully continues to the next statement in the test method. You can get the error text of the statement by
using the GetLastErrorText method.
If a statement that follows the AssertError keyword doesn't cause an error, then the AssertError statement
causes the following error and the test method that is running produces a FAILURE result:

TestAsserterrorFail: FAILURE

An error was expected inside an AssertError statement.

Example
To create a test method to test the result of a failure of a CheckDate method that you've defined, you can use the
following code. This example requires that you create a method called CheckDate to check whether the date is
valid for the customized application.

InvalidDate := 19000101D;
InvalidDateErrorMessage := Text001;
AssertError CheckDate(InvalidDate);

IF GetLastErrorText <> InvalidDateErrorMessage then


Error('Unexpected error: %1', GetLastErrorText);

This example requires the following variables.

var
InvalidDate : Date;
InvalidDateErrorMessage : Text;
Text001 : Label 'The date is outside the valid date range.';

With statements (to be deprecated)


IMPORTANT
Using the with statement is being deprecated with Dynamics 365 Business Central 2020, release wave 2. With this
release it is a warning, which will become an error in a future release.
Using with statements introduces possible uniqueness collisions when multiple extensions contribute to the same
objects because it allows working with members using just simple names instead of qualifying them. To avoid this going
forward, we are marking the use of with , be it implicit or explicit as warnings. With this release, you can use a quick
action to fix these files, as well as suppress obsolete warnings for now. Code that contains with statements will, however,
need to be refactored before with statements are compiled with errors. For more information, see Deprecating Explicit
and Implicit With Statements. For information about using directives in code, see Directives in AL and Pragma ImplicitWith
Directive in AL.

The following syntax shows a with-do statement.

with <Record> do
<Statement>

When you work with records, addressing is created as record name, dot (period), and field name:
<Record>.<Field>
If you work continuously with the same record, then you can use with statements. When you use a with
statement, you can only specify the record name one time.
Within the scope of <Statement>, fields in <Record> can be addressed without having to specify the record
name.
You can nest several with statements. If you have identical names, then the inner with statement overrules the
outer with statement.
Example
This example shows two ways to write the same code that creates a record variable that you can commit later.
CustomerRec."No." := '1234';
CustomerRec.Name := 'Windy City Solutions';
CustomerRec."Phone No." := '555-444-333';
CustomerRec.Address := '1241 Druid Avenue';
CustomerRec.City := 'Windy City';
Message('A variable has been created for this customer.');

This example requires the following variables.

var
CustomerRec : Record Customer;

The following example shows another way to create a record variable that you can commit later:

with CustomerRec do begin


"No." := '1234';
Name := 'Windy City Solutions';
"Phone No." := '555-444-333';
Address := '1241 Druid Avenue';
City := 'Windy City';
Message('A variable has been created for this customer.');
end;

Programming conventions
Within with-do blocks, don't repeat the name of the object by using the member variable or method.
If you nest a with-do block within another explicit or implicit with-do block, then the with-do block that you
create within another with-do block must always be attached to a variable of the same type as the variable that
is attached to the surrounding with-do block. Otherwise, it can be difficult to see what variable that a member
variable or method refers to. For example, implicit with-do blocks occur in table objects and in pages that have
been attached to a record.
Example
The following example demonstrates nested with-do blocks. Both with-do blocks are attached to a Customer
Ledger Entry record variable.

with CustLedgEntry do begin


Insert;
...;
with CustLedgEntry2 do begin
Insert;
...;
end;
end;

Incorrect example
The following example demonstrates incorrect code in which you can't directly tell which record variable that the
MyField field refers to.

with CustLedgEntry do begin


...;
with VendLedgEntry do begin
MyField := <Some Value>;
...;
end;
end;
See Also
Control Statements
Methods
Directives in AL
AL Essential Methods
AL Control Statements
2/6/2023 • 13 minutes to read • Edit Online

AL code consists of one or more statements, which are executed sequentially in a top-down order. However,
you'll often need to control the direct top-down flow of the execution. One or more statements may have to be
repeated more than once, or you may have to make the execution of a certain statement conditional. To do so,
you use control structures.
The control structures in AL are divided into the following main groups, as described in this article:
AL Compound Statements
AL Conditional Statements
AL Repetitive Statements

NOTE
In the following sections, conventions for how to structure and align AL code are presented to introduce best practices. In
many cases, the structure isn't necessary to get the code to compile, but rather to improve readability.

AL compound statements
In some cases, the AL syntax only lets you use a single statement. However, if you have to run more than one
simple statements, the statements can be written as a compound statement by enclosing the them between the
begin and end keywords.

begin
<Statement 1>;
<Statement 2>;
..
<Statement n>;
end;

The individual statements are separated by a semicolon. In AL, a semicolon is used to separate statements and
not to terminate them, as in other programming languages. Nevertheless, an extra semicolon before an end
doesn't cause an error because it's interpreted by the compiler as an empty statement.

Blocks
The begin-end structure is also called a block. Blocks can be useful to refer to the other control structures in AL.
When begin follows, then, else, or do should be on the same line and preceded by one space character.
Example

if (x = y) and (a = b) then begin


x := a;
y := b;
end;

Example
if (xxx = yyyyyyyyyy) and
(aaaaaaaaaa = bbb)
then begin
x := a;
x := y;
a := y;
end else begin
y := x;
y := a;
end;

AL conditional statements
You use conditional statements to specify a condition and one or more commands to execute if the condition is
evaluated as true or false. There are two types of conditional statements in AL:
if-then-else, where there are two choices
case, where there are more than two choices
If-then-else statements
if-then-else statements have the following syntax.

if <Condition> then
<Statement1>
[else
<Statement2>]

If <Condition> is true, then <Statement1> is executed. If <Condition> is false, then <Statement2> is executed.
The square brackets around else <Statement2> mean that this part of the statement is optional. The else
statement is used when different actions are executed depending on how <Condition> is evaluated.
You can build more complex control structures by nesting if-then-else statements. The following example is a
typical if-then-else statement.

if <Condition1> then
if <Condition2> then
<Statement1>
else
<Statement2>

If <Condition1> is false, then nothing is executed. If <Condition1> and <Condition2> are both true, then
<Statement1> is executed. If <Condition1> is true and <Condition2> is false, then <Statement2> is executed.

NOTE
A semicolon in front of an else statement is not allowed.

Reading several nested if-then-else statements can be confusing but generally, an else statement belongs to the
last if statement that lacks an else statement.
Programming conventions
if and then should be on the same line, else should be on a separate line.
If there are many or long expressions, then should be on a new line and be aligned with if .
When you write if expressions with then and else parts, write them so that the then result is more
probable than the else one.
If the last statement in the then part of an if-then-else statement is an exit or an error , don't
continue with an else statement.
Example

if x = y then
x := x + 1
else
x := -x - 1;

Example

if (xxxxxxxxxx = yyy) and


(aaa = bbbbbbbbbb)
then
x := a
else
y := b;

Example

if x <> y then
exit(true);
x := x * 2;
y := y - 1;

Incorrect example

if x < y then
exit(true)
else begin
x := x * 2;
y := y - 1;
end;

Example
The following example shows an if-then statement without the optional else statement.

if Amount < 1000 then


Total := Total + Amount;

Example
The following example shows a nested if-then-else statement.

...
if Amount < 1000 then begin
if I > J then
Max := I
else
Max := J;
Amount := Amount * Max;
end;
else
...
Case statements
Case statements have the following syntax.

case <Expression> of
<Value set 1>:
<Statement 1>;
<Value set 2>:
<Statement 2>;

<Value set n>:


<Statement n>;
[else
<Statement n+1>]
end;

In this definition, the result of <Expression> is matched against each value set and <Value set> must be an
expression or a range.

NOTE
<Expression> cannot be an application object variable, since application objects don't have a comparator.

Case statements are also called multiple option statements and are typically used when you must choose
between more than two different actions. The method of the case statement is as follows:
The <Expression> is evaluated, and the first matching value set executes the associated statement, if
there's one.
If no value set matches the value of the expression and the optional else part has been omitted, then no
action is taken. If the optional else part is used, then the associated statement is executed.
The data type of the value sets must be the same as the data type of <Expression> or at least be convertible to
the same data type.
In most cases, the data type of the value sets is converted to the data type of the evaluated expression. The only
exception is if the evaluated expression is a Code variable. If the evaluated expression is a Code variable, then
the value sets aren't converted to the Code data type.

NOTE
This type conversion can cause an overflow at run time if the resulting data type cannot hold the values of the datasets.

For more information about Code variables, see Code Data Type.
Programming conventions
When you use a case statement, indent the value sets by four character spaces. If you've two or more value sets
on the same line, then separate them by commas without spaces. The last value set on a line is immediately
followed by a colon without a preceding space. The action starts on the line after the value set and is further
indented by four character spaces. If there's a begin, then it should be put on a separate line unless it follows
else. If a begin follows an else, then it should be on the same line as else.
If there are more than two alternatives, use a case statement. Otherwise, use an if-then-else statement.
Example
case Field of
Field::A:
begin
x := x + 1;
y := -y - 1;
end;
Field::B:
x := y;
Field::C,Field::D:
y := x;
else begin
y := x;
a := b;
end;
end;

Example
The following AL code prints various messages depending on the value of Number. If the value of Number
doesn't match any of the entries in the case structure, then the else entry is used as the default.

case Number of
1,2,9:
message('1, 2, or 9.');
10..100:
message('In the range from 10 to 100.');
else
message('Neither 1, 2, 9, nor in the range from 10 to 100.');
end;

Example
The following AL code shows how value sets in a case statement are evaluated if the expression is a Code data
type.

MyCode := 'ABC';
case MyCode of
'abc':
message('This message is not displayed.');
'def':
message('This message is not displayed.');
else
message('The value set does not match the expression.');
end;

This example requires that you create the following code data type variable.

var
MyCode : Code[10];

The value set 'abc' isn't converted because the evaluated expression MyCode is a code variable.

AL repetitive statements
A repetitive statement is also known as a loop. The following table shows the looping mechanisms in AL.

LO O P IN G M EC H A N ISM DESC RIP T IO N


LO O P IN G M EC H A N ISM DESC RIP T IO N

for Repeats the inner statement until a counter variable equals


the maximum or minimum value specified.

foreach Repeats the inner statement for each statement in a List,


XmlNodeList, XmlAttributeCollection, or JsonArray.

while Repeats the inner statement as long as the specified


condition is true . The statement in a loop of this kind is
repeated zero or more times.

repeat Repeats the inner statements until the specified conditions


evaluate to true . The statements in a loop of this kind are
always executed at least one time.

For-to and for-downto control structure


The following syntax shows the for-to and for-downto statement.

for <Control Variable> := <Start Number> to <End Number> do


<Statement>

for <Control Variable> := <Start Number> downto <End Number> do


<Statement>

The data type of <Control Variable> , <Start Number> , and <End Number> must be Boolean, number, time, or
date.
Use for-to and for-downto statements when you want to execute code for a specific number of times. The
<Control Variable> controls the number of times that the code of the inner statement is executed according to
the following:
In a for-to loop statement, the <Control Variable> value is increased by one after each iteration. The
inner <Statement> is executed repeatedly until the *<Start Number> * value is greater than the
*<End Number>* value.

In a for-downto loop statement, the <Control Variable> value is decreased by one after each iteration.
The inner <Statement> is executed repeatedly until the <Start Number> value is less than the
<End Number> value.

NOTE
When the for statement is executed, <Start Number> and <End Number> are converted to the same data type as
<Control Variable> if it's required. This type conversion can cause a run-time error.

NOTE
If the value of the <Control Variable> is changed inside the for loop, then the behavior is not predictable.
Furthermore, the value of the <Control Variable> is undefined outside the scope of the for loop.

Example 1
The following code initiates a for loop that uses the integer control variable named Count.
for Count := 1000 to 100000000000000 do

This example requires the following Integer data type variable.

var
Count : Integer;

When this statement is executed, then a run-time error occurs because the start, and end values are converted
to the same data type as the Count control variable. Count has been declared as an integer variable. The end
number 100000000000000 is outside the valid range for integers, and an error occurs.
Example 2
The following example shows how to nest for statements.
Set the Dimensions property of variable A to 5;7.
The following for statements could be used to initialize every element in a 5x7 array with the value 23.

for I := 1 to 5 do
for J := 1 to 7 do
A[I,J] := 23;

This example requires the following Integer data type variables.

var
I : Integer;
J : Integer;

Foreach control structure


You can use the foreach statement to iterate through List, XmlNodeList, XmlAttributeCollection, and JsonArray
expressions. The foreach statement has the following syntax.

foreach <Element> in <List> do


<Statement>

The <List> variable must be of the List, XmlNodeList, XmlAttributeCollection, or JsonArray type. The <Element>
variable must be a data type that is compatible with elements specified by the <List> .
The following code example iterates through a list of customer names and returns each customer name in a
message.

procedure PrintCustomerNames(customerNames : List of [Text]);


var
customerName : Text;
begin
foreach customerName in customerNames do
message(customerName);
end;

While -do control structure


The following syntax shows the while-do statement.
while <Condition> do
<Statement>

If <Condition> is true, then <Statement> is executed repeatedly until <Condition> becomes false. If
<Condition> is false from the start, then <*Statement> is never executed.
The while do statement can be used when some code should be repeated as long as an expression is true.
Programming conventions
When there's only one condition, put while and do on the same line. Put the statements on separate lines and
indented by two spaces.
When there are multiple conditions, put the conditions on separate lines, and indented by two spaces and put
do on a separate line that is aligned with while .

Example

while <expr> do
<Statement>;

Example

while <expr> do begin


<Statement>;
<Statement>;
end;

Example

while <expr> and


<expr> and
<expr>
do begin
<Statement>;
<Statement>;
end;

Example
The following AL code increases the variable I until it equals 1000 and displays a message when it's finished.

while I < 1000 do


I := I + 1;
message(format(I));

This example requires the following integer data type variable.

var
I : integer

Repeat-until control structure


The following syntax shows the repeat-until statement.

repeat
<Statements> until <Condition>
<Statements> is executed repeatedly until <Condition> is true.
The repeat until control structure resembles the while control structure. The difference is that because the
repeat until statement is executed from left to right, the <Statements> is always executed at least one time,
regardless of what the <Condition> is evaluated to. This contrasts with the while control structure, which
performs the evaluation before the <Statement> is executed. In the while control structure, if the first
evaluation of <Condition> returns false, then no statements are executed.
Programming conventions
Always put repeat on a separate line.
Example

if x < y then begin


repeat
x := x + 1;
a := a - 1;
until x = y;
b := x;
end;

Example
This code uses a repeat-until loop to count the number of entries in the Customer table.

Count := 0;
if Customer.find('-') then
repeat
Count := Count + 1;
until Customer.next <= 0;
message('The Customer table contains %1 records.',Count);

This example requires the following variables.

var
Count : Integer;
Customer : Record Customer;

The find method finds the first entry in the table. Each time NEXT is called, it steps one record forward. When
NEXT equals 0, there are no more entries in the table. The loop is exited, and a message displays how many
entries were found.
Exit statement
The exit statement is used to control the flow of the execution. The following syntax shows an exit statement.

exit([<Value>])

An exit statement is used to interrupt the execution of an AL trigger. The interruption occurs even when the code
is executed inside a loop or a similar structure. The exit statement is also used when a local method should
return a value.
Using exit without a parameter in a local method corresponds to using the parameter value 0. The AL method
will return the value 0 or '' (empty string).
A compile-time error occurs if exit is called by using a return parameter from either:
System-defined triggers, or
Local methods that don't return a value.
Example
The following example shows the use of the exit statement in a local method. Assume that the if statement is
used to detect an error. If the error condition is met, then execution is stopped and the local method returns the
error code 1.

for I := 1 to 1000 do begin


if Amount[I] < Total[I] then
exit(1);
A[I] := Amount[I] + Total[I];
end;

Break statement
You use the break statement to terminate the iterative statement in which it appears.

break;

You typically use the break statement in the repeating statements such as for , while , or repeat to stop an
iteration or loop when certain conditions are met.

NOTE
The break statement is different than the Break Method (Report, XMLport). Although both stop an iteration or loop, the
break method will also terminate the trigger in which it's run.

Example
The following AL code increases the variable I by one for each iteration, and terminates the iteration when I
equals 10.

while Count < 1000 do


begin
Count := Count + 1;
message(FORMAT(Count));
if Count = 10 then
break;
end;
end;

This example requires the following integer data type variable.

var
I : integer

See Also
Programming in AL
AL Simple Statements
Directives in AL
AL Essential Methods
Using Access Modifiers in AL
2/6/2023 • 2 minutes to read • Edit Online

Access modifiers are used to set accessibility of tables, table fields, codeunits, and queries, which controls
whether the object can be used from other code in your module or other modules. Access modifiers in AL are
designed to create solid APIs, by limiting the symbols that dependant modules can take a reference on. Limiting
the API surface can hide implementation details and allow for later refactoring of code without breaking external
code.
You set the object accessibility by using the Access Property. If the Access property isn't specified; default is
Public .

NOTE
In AL, access modifiers are primarily intended for designing APIs and cannot be used as a security boundary.

Access modifiers
The access modifiers that are available in AL are:

A C C ESS M O DIF IER DESC RIP T IO N

internal The object or field can be accessed only by code in the same
module, but not from another module.
Note: This accessibility level is controlled by the
internalsVisibleTo setting. For more information, see
JSON Files

local The field can be accessed only by code in the same table or
table extension where the field is defined.
Note: Applies to table fields only.

protected The field can be accessed only by code in the same table or
table extensions of that table.
Note: Applies to table fields only.

public The object or field can be accessed by any other code in the
same module and in other modules that references it.
Note: This is the default value.

Setting access to internal is linked to the JSON Files setting internalsVisibleTo .

IMPORTANT
Access modifiers are only taken into consideration at compile time. For example, at compile time, a table with
Access = Internal can't be used from other modules that don't have access to the internals of the module where the
table is defined, but at runtime, any module can access the table by using reflection-based mechanisms such as
RecordRef , or TransferFields . And the OnRun trigger can be run on internal codeunits by using Codeunit.Run .
Setting the object accessibility level as Access = Internal; cannot be used as a security boundary. Also see JSON Files.
See Also
AL Development Environment
Access Property
XML Comments in Code
2/6/2023 • 4 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

In Dynamics 365 Business Central, you can add documentation directly in your source code by including XML
elements in special comment fields before the block of code that the comment refers to. The documentation
comment must immediately precede a user-defined type that it annotates, for example a codeunit, table,
interface, or a member such as a field or method. The syntax for adding XML comments in your code is triple
slashes /// followed by one of the supported XML tags. There's IntelliSense support for writing documentation
comments that also provides a template comment on entering the third slash in the triple slash.
Documentation comments are visible when you hover over source symbols, in completion lists, and in signature
help. By adding XML comments in code, you can improve readability, add useful information about the
implementation, and help others take over code that you wrote. With XML comments, you also enable
IntelliSense in Visual Studio Code on the AL objects that you add in the code as a help to other developers,
working with or extending your code. When your code is documented using XML comments, it means that when
you've built an extension and someone extends this code, they'll get inline documentation when they call the
given object.

NOTE
Integration with documentation generator tools like DocFx and SandCastle is currently not supported.

NOTE
If you have the allowDownloadingSource setting in the app.json file set to false and you then download an app
package; the app package won't contain any XML comments.

Supported XML tags


The following table lists the XML elements that are supported for AL.

TO P - L EVEL XM L TA G DESC RIP T IO N SY N TA X

<summary> A summary of the object <summary>description</summary>

<param> Used in method declarations to <param


describe one or more parameters name="name">description</param>
defined in the method. For each
parameter, specify the name and a
description.

<returns> Used in method declarations to <returns>description</returns>


describe the return value of the
method.

<example> Used to specify an example of how to <example>description</example>


use a given codeunit or object.
TO P - L EVEL XM L TA G DESC RIP T IO N SY N TA X

<remarks> Used to supplement information given <remarks>description</remarks>


in the <summary> section.

F O RM AT T IN G XM L TA G DESC RIP T IO N SY N TA X

<paramref> Specifies a reference to a parameter in <paramref name="name"/>


a <summary> or <remarks> block.

<para> Allows structuring text inside a <para>paragraph</para>


<summary> , <remarks> , or
<returns> tag.

<b> Allows formatting text as bold inside a <b>bold</b>


top-level tag.

<i> Allows formatting text as italic inside a <i>italic</i>


top-level tag.

<c> Specifies that text within a description <c>inline code</c>


should be marked as code inside a
top-level tag.

<code> Specifies that multiline text within a <code>code block</code>


description should be marked as code
inside a top-level tag.

<list> Specifies a list formatted as a bulleted <list


or numbered list, or as a table in a type="bullet|number|table">
<summary> or <remarks> block. . See full List syntax below.

List syntax

<list type="bullet|number|table">
<listheader>
<term>term</term>
<description>description</description>
</listheader>
<item>
<term>term</term>
<description>description</description>
</item>
</list>

Example
The following example is taken from the Email.Codeunit.al file in the System Application. In this example, the
parameter EmailMessageId is documented using the <param> syntax.
/// <summary>
/// Provides functionality to create and send e-mails.
/// </summary>

codeunit 8901 "Email"


{
Access = Public;

/// <summary>
/// Enqueues an email in the outbox to be sent in the background.
/// </summary>
/// <param name="EmailMessageId">The ID of the email to enqueue</param>
procedure Enqueue(EmailMessageId: Guid)
begin
EmailImpl.Enqueue(EmailMessageId);
end;
...

Special symbols
For special symbols, such as angle brackets, to appear in text of a documentation comment, use the HTML
encoding of < and > , which is &lt; and &gt; respectively. The following example illustrates how.

/// <summary>
/// This property always returns a value &lt; 1.
/// </summary>

Writing tips
Code comments improve the readability of the code that you've developed and they're useful for anyone
modifying or maintaining that code. Furthermore, code comments form the basis of auto-generated
documentation. Great code comments must do the following:
1. Never state the obvious.
2. Write a meaningful comment, use precise wording to describe why.
3. Imagine yourself in the shoes of the developer using this piece of code, what would you want to know?
4. For properties and methods, use active wording such as Sets..., Gets..., and Specifies..., and then explain what
it does.
5. List all pre-conditions for your parameters (can't be null, must be within a certain range, and so on).
6. List any post-conditions that could influence how callers deal with return values.
7. List any exceptions the method may throw (and under what circumstances).
8. If similar methods exist, explain the differences between them.
9. Call attention to anything unexpected (such as modifying global state).
10. Enumerate any side-effects, if there are any.
11. Be consistent.
12. Be concise.
13. Make sure that your comments are reviewed.
For more examples, see https://stackoverflow.com/questions/3143324/what-are-best-practices-for-
documenting-c-sharp-code-with-xml-comments.

See also
AL Development Environment
Developing Extensions in AL
Pages Overview
Microsoft Writing Style Guide
Data Types and Methods in AL
2/6/2023 • 9 minutes to read • Edit Online

The following data types are available as part of the AL Language. Each data type has various methods that
support it. For more information about a data type and its methods, select a link in the table.

TYPE DESC RIP T IO N

Any This data type can be substituted by any other data type.

BigInteger Stores very large whole numbers that range from -


9,223,372,036,854,775,807 to 9,223,372,036,854,775,807.

BigText Handles large text documents.

Blob Is a complex data type. Variables of this data type differ from
normal numeric and string variables in that BLOBs have a
variable length. The maximum size of a BLOB(binary large
object) is 2 GB.

Boolean Indicates true or false.

Byte Stores a single, 8-bit character as a value in the range 0 to


255. You can easily convert this data type from a number to
a character and vice versa. This means you can use
mathematical operators on Byte variables.

Char Stores a single, 16-bit character as a value in the range 0 to


65535. You can convert this data type from a number to a
character and vice versa. This means you can use
mathematical operators on Char variables.

Code Denotes a special type of string that is converted to


uppercase and removes any trailing or leading spaces.

Codeunit Is a container for AL code that you can use from other
application objects.

CompanyProperty Provides language support for company properties.

Database Provides access to common database functionality.

DataTransfer A structure building bulk transfer of data between tables.

Date Denotes a date ranging from January 1, 1753 to December


31, 9999.

DateFormula Represents a date formula that has the same capabilities as


an ordinary input string for the CALCDATE Method (Date).
The DateFormula data type is used to provide multilanguage
capabilities to the CALCDATE Method (Date).
TYPE DESC RIP T IO N

DateTime Denotes a date and time ranging from January 1, 1753,


00:00:00.000 to December 31, 9999, 23:59:59.999. An
undefined or blank DateTime is specified by 0DT.

Debugger Enables communication with a debugger.

Decimal Denotes decimal numbers ranging from -


999,999,999,999,999.99 to +999,999,999,999,999.99.

Dialog Represents a dialog window.

Dictionary Represents an unordered collection of keys and values. The


Dictionary data type is optimized for fast lookup of values.

DotNet Represents an unspecified .NET type.

Duration Represents the difference between two DateTimes. This value


can be negative. It is stored as a 64-bit integer. The integer
value is the number of milliseconds during the duration.

Enum Represents the text content of an element or attribute.

ErrorInfo Provides a structure for grouping information about an error.

FieldRef Identifies a field in a table and gives you access to this field.

File Represents a file.

FilterPageBuilder Stores filter configurations for a filter page. A filter page is a


dynamic page type that contains one or more filter controls
that enables users to set filters on fields of the underlying
tables.

Guid Represents a 16 byte binary data type. This data type is used
for the global identification of objects, programs, records,
and so on. The important property of a GUID is that each
value is globally unique. The value is generated by an
algorithm, developed by Microsoft, which assures this
uniqueness.

HttpClient Provides a data type for sending HTTP requests and


receiving HTTP responses from a resource identified by a
URI.

HttpContent Represents an HTTP entity body and content headers.

HttpHeaders Is a collection of headers and their values.

HttpRequestMessage Represents an HTTP request message.

HttpResponseMessage Represents an HTTP response message including the status


code and data.
TYPE DESC RIP T IO N

InStream Is a generic stream object that you can use to read from or
write to files and BLOBs. You can define the internal structure
of a stream as a flat stream of bytes. You can assign one
stream to another. Reading from and writing to a stream
occurs sequentially.

Integer Stores whole numbers with values that range from -


2,147,483,647 to 2,147,483,647.

IsolatedStorage Provides data isolation for extensions.

JsonArray Is a container for any well-formed JSON array. A default


JsonArray contains an empty JSON array.

JsonObject Is a container for any well-formed JSON object. A default


JsonObject contains an empty JSON object.

JsonToken Is a container for any well-formed JSON data. A default


JsonToken object contains the JSON value of NULL.

JsonValue Is a container for any well-formed fundamental JSON value.


A default JsonValue is set to the JSON value of NULL.

KeyRef Identifies a key in a table and the fields in this key.

Label Denotes a string constant that can be optionally translated


into multiple languages.

List Represents a strongly typed list of ordered objects that can


be accessed by index. Contrary to the Array data type, a List
is unbounded, such that its dimension does not need to be
specified upon declaration.

Media Encapsulates media files, such as image .jpg and .png files, in
application database tables. The Media data type can be
used as a table field data type, but cannot be used as a
variable or parameter. The Media data type enables you to
import a media file to the application database and reference
the file from records, making it possible to display the media
file in the client user interface. You can also export media
from the database to files and streams.

MediaSet Encapsulates media, such as images, in application database


tables.

ModuleDependencyInfo Provides information about a dependent module.

ModuleInfo Represents information about an application consumable


from AL.

NavApp Provides information about a NavApp.

None Is used implicitly when a method does not return a value.


TYPE DESC RIP T IO N

Notification Provides a programmatic way to send non-intrusive


information to the user interface (UI) in the Business Central
Web client.

NumberSequence Is a complex data type for creating and managing number


sequences in the database.

Option Denotes an option value. In the code snippet below, you can
see how the Option data type is declared.

OutStream Is a generic stream object that you can use to write to files
and BLOBs.

Page Contains a number of simpler elements called controls.


Controls are used to display information to the user or
receive information from the user.

ProductName An application can have a full name, marketing name, and


short name. The PRODUCTNAME functions enable you to
retrieve these name variations.

Query Enables you to retrieve data from multiple tables and


combine the data in single dataset.

Record Is a complex data type.

RecordId Contains the table number and the primary key of a table.

RecordRef References a record in a table.

Report Is used to display, print, or process information from a


database.

RequestPage Is a page that is run before the report starts to execute.


Request pages enable end-users to specify options and
filters for a report.

Session Represents a Microsoft Dynamics Business Central session.

SessionInformation Is a complex data type for exposing Session information into


AL.

SessionSettings Is a complex data type for passing user personalization


settings for a client session as an object. The object contains
properties that correspond to the fields in the system table
2000000073 User Personalization , including: App ID,
Company, Language ID, Locale ID, Profile ID, Scope, and Time
Zone. You can use the AL methods of the SessionSettings
data type to get, set, and send the user personalization
settings for the current client session.

System Is a complex data type.


TYPE DESC RIP T IO N

TaskScheduler Is a complex data type for creating and managing tasks in


the task scheduler, which runs codeunits at scheduled times.

TestAction Represents a test action on a page.

TestField Represents a testable field on a page.

TestFilter Represents a test filter on a page.

TestFilterField Represents the type of a field filter in a test filter on a page


or on a request page.

TestPage Represents a variable type that can be used to test Page


Application Objects.

TestPart Represents a variable type that can be used to test Page


Application Objects of type Part.

TestRequestPage Stores test request pages. A test request page part is a


logical representation of a request page on a report. A test
request page does not display a user interface (UI). The
subtype of a test request page is the report whose request
page you want to test.

Text Denotes a text string.

TextBuilder Represents a lighweight wrapper for the .Net implementation


of StringBuilder.

TextConst Denotes a multi-language string constant.

Time Denotes a time ranging from 00:00:00.000 to 23:59:59.999.


An undefined or blank time is specified by 0T.

Variant Represents an AL variable object. The AL variant data type


can contain many AL data types.

Version Represents a version matching the format:


Major.Minor.Build.Revision .

WebServiceActionContext Represents an AL WebServiceActionContext.

XmlAttribute Represents an XML attribute.

XmlAttributeCollection Represents a collection of XML attributes.

XmlCData Represents a CData section.

XmlComment Represents an XML comment.

XmlDeclaration Represents an XML declaration.


TYPE DESC RIP T IO N

XmlDocument Represents an XML document.

XmlDocumentType Represents an XML document type.

XmlElement Represents an XML element.

XmlNamespaceManager Represents a namespace manager that can be used to


resolve, add and remove namespaces to a collection. It also
provides scope management for these namespaces.

XmlNameTable Represents a table of atomized string objects.

XmlNode Represents a XML node which can either be for instance an


XML attribute, an XML element or a XML document.

XmlNodeList Represents a collection of XML nodes.

Xmlport XmlPorts are used to export or import data between an


external source and a Microsoft Dynamics Business Central
database.

XmlProcessingInstruction Represents a processing instruction, which XML defines to


keep processor-specific information in the text of the
document.

XmlReadOptions Represents the options configuring how XML is loaded from


a data source.

XmlText Represents the text content of an element or attribute.

XmlWriteOptions Represents the options configuring how XML is saved.

Action Represents the action that the user took on the page.

AuditCategory Represents an audit category for IfX audit telemetry.

ClientType Represents the type of the client executing the operation.

CommitBehavior Specifies whether commit is allowed within the scope of the


method.

DataClassification Sets the classification of the data in the table or field.

DataScope Identifies the scope of stored data in the isolated storage.

DefaultLayout The default layout to be used by a report.

ErrorBehavior Specifies whether errors will be collected within the scope of


the method.

ErrorType Represents the type of error.


TYPE DESC RIP T IO N

ExecutionContext Represents the context in which a session is running. In


certain scenarios, for example during upgrade, the system
will run a session in a special context for a limited time.

ExecutionMode The execution mode of the current session.

FieldClass Represents the type of a field class.

FieldType Represents the type of a table field.

InherentPermissionsScope The different types of scope that the InherentPermissions


attribute can apply to.

NotificationScope Specifies the context in which the notification appears in the


client.

ObjectType The different types of objects.

PageBackgroundTaskErrorLevel Specifies how an error in the page background task appears


in the client.

PermissionObjectType The different types of objects that can have different


permissions assigned.

ReportFormat Specifies the format of the report.

ReportLayoutType Represents the type of a report layout.

SecurityFilter Specifies how security filters are applied to the record.

SecurityOperationResult Represents security audit operation result.

TableConnectionType Use variables of this data type to specify the type of


connection to an external database.

TelemetryScope Represents the emission scope of the telemetry signal.

TestPermissions Specifies a value that can be used to determine which


permission sets are used on tests that are run by test
codunits or test functions.

TextEncoding Represents a file encoding.

TransactionModel Represents a test transaction model.

TransactionType Represents a transaction type.

Verbosity Represents the security level of events.

WebServiceActionResultCode Represents a web service action status code.


See Also
Get Started with AL
Developing Extensions
Date Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Denotes a date ranging from January 1, 1753 to December 31, 9999.


The displayed text format of the date is determined by your Region and Language Format setting in Windows.

Undefined dates
An undefined or blank date is specified by 0D. The undefined date is considered to be before all other dates.

Normal dates and closing dates


All normal dates have a corresponding closing date. The closing date for a given date is defined as a period of
time that follows a given normal date and precedes the next normal date.

Syntax
The syntax for defining DateTime format follows the ISO standard.
The syntax for defining Date format is yyyymmddD , where D is a mandatory letter. For example, 20180325D ,
read as the 25th of March, 2018.
To assign a normal date to a variable, use the following format: yyyymmddD .

Storing dates in the SQL server database


SQL Server stores information about both date and time in columns of the DateTime types. For date fields,
Dynamics 365 Business Central uses only the date and uses a constant value for the time. For a normal date, this
constant value contains 00:00:00:000. For a closing date, it contains 23:59:59:000.
The Dynamics 365 Business Central undefined date is represented by the earliest valid date in SQL Server. The
earliest valid date in SQL Server for a DateTime is 01-01-1753 00:00:00:000.
If you store a date in the database that is outside the valid range for a SQL DateTime, a run-time error occurs.

Example
This example shows a valid assignment of date. This example is compiled and run on a computer with the
regional format set to English (United States).

var
Date1: Date;
begin
Date1 := 20180612D;
Message(Format(Date1));
end;

The message window displays the following:


06/12/2018

See Also
Get Started with AL
Developing Extensions
About Dates in Business Central
DateTime Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Denotes a date and time ranging from January 1, 1753, 00:00:00.000 to December 31, 9999, 23:59:59.999. An
undefined or blank DateTime is specified by 0DT.
The displayed text format of a DateTime is determined by your Regional and Language Options in Windows.

Remarks
A DateTime is stored in the database as Coordinated Universal Time (UTC). UTC is the international time
standard (formerly Greenwich Mean Time, or GMT). Zero hours UTC is midnight at 0 degrees longitude.
The DateTime is always displayed as local time in Dynamics 365 Business Central. Local time is determined by
the time zone regional settings used by your computer. You must always enter DateTimes as local time. When
you enter a DateTime as local time, it is converted to UTC using the current settings for the time zone and
daylight savings time.
The DateTime data type does not support closing dates.
By default, DateTimes are displayed using the standard display format. When you use the standard display
format, seconds and milliseconds are not displayed until you select the DateTime field. Furthermore, if you
export your data using an XMLport or by writing it to a file, the seconds and milliseconds are not exported
unless you specify that DateTime fields use another format and display this information. For more information
about how DateTime objects are displayed and the formats that are available, see Formatting Values, Dates, and
Time.
The only constant available when you use the DateTime data type is the undefined DateTime, 0DT. To assign a
constant value to a DateTime variable you must use the CreateDateTime method.
If you use a date that is outside the valid date range, a run-time error occurs.

Syntax
The syntax for defining DateTime format follows the ISO standard.
The syntax for defining Date format is yyyymmddD , where D is a mandatory letter. For example, 20180325D ,
read as the 25th of March, 2018.
The syntax for defining Time format is hhmmssT , where T is the time designator. For example, 093125H , read
as 9:13:25.

SQL Server
In SQL Server, the earliest permitted DateTime is January 1, 1753, 00:00:00.000. The latest permitted DateTime
is December 31, 9999, 23:59:59.999. If you store a date in the database that is outside the valid range for a SQL
DateTime, a runtime error occurs.

See Also
Get Started with AL
Developing Extensions
About Dates in Business Central
CurrentDateTime Method
Formatting Values, Dates, and Time
Duration Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents the difference between two DateTimes. This value can be negative. It is stored as a 64-bit integer. The
integer value is the number of milliseconds during the duration.
The following are examples of durations:
DateTime-DateTime=Duration
DateTime-Duration=DateTime
DateTime+Duration=DateTime
The value of the Duration data type can also be explicitly defined in milliseconds.

Example 1
This example shows how to calculate the difference between two DateTimes. This example is run on a computer
with the Current Format in the Regional and Language Options set to English (United States).

var
DateTime1: DateTime;
DateTime2: DateTime;
Duration: Duration;
begin
DateTime1 := CreateDateTime(20090101D, 080000T); // January 1, 2009 at 08:00:00 AM
DateTime2 := CreateDateTime(20090505D, 133001T); // May 5, 2009 at 1:30:01 PM
Duration := DateTime2 - DateTime1;
Message(Format(Duration));
end;

The message window displays the following:


124 days 4 hours 30 minutes 1 second

Example 2
The following example shows how to specify the duration of a timeout in milliseconds.

procedure GetDefaultTimeout(): Duration


var
Timeout: Duration;
begin
Timeout := 1000 * 60 * 60; // One hour
exit(Timeout);
end

See Also
Get Started with AL
Developing Extensions
Time Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Denotes a time ranging from 00:00:00.000 to 23:59:59.999. An undefined or blank time is specified by 0T.
The displayed text format of the time is determined by your Regional and Language Options in Windows.
The following are examples of valid assignments of times to a Time variable MyTime. Time must be set by
specifying hours, minutes, and seconds.

MyTime := 0T;
MyTime := 115900T;
Message(Format(MyTime));
MyTime := 115934T;
Message(Format(MyTime));
MyTime := 115934.444T;
Message(Format(MyTime));
MyTime := 235900T;
Message(Format(MyTime));
MyTime := 030000T;
Message(Format(MyTime));

The following shows what the message windows display accordingly on a computer with the regional format set
to English (United States) for the syntax examples above.
11:59:00 AM
11:59:34 AM
11:59:34.444 AM
11:59:00 PM
3:00:00 AM

SQL Server
Microsoft SQL Server stores information about both date and time in columns of the DATETime type. Dynamics
365 uses only the time part and inserts a constant value for the date: 01-01-1754.
The Dynamics 365 undefined time is represented by the same value as an undefined date. The undefined date is
represented by the earliest valid DateTime in SQL Server, which is 01-01-1753 00:00:00:000.

See Also
Get Started with AL
Developing Extensions
Integer Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Stores whole numbers with values that range from -2,147,483,647 to 2,147,483,647.

Remarks
In addition to representing whole numbers in this range, you can use integers to represent Boolean values. For
Boolean values, 1 represents true and 0 represents false .
If you assign -2,147,483,648 directly to an Integer variable, then you get an error when you try to compile the
code. However, you can indirectly assign -2,147,483,648 to an Integer variable by using the following code.

IntegerVar := -2147483647;
IntegerVar -= 1;

If you try to indirectly assign a value that is smaller than -2,147,483,648 or larger than 2,147,483,647, then you
get a run-time error.

Example 1
The following are examples of integer values.

546
-3425

Example 2
The following example is a decimal and not an integer.

342.45

See Also
Get Started with AL
Developing Extensions
BigInteger Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Stores very large whole numbers that range from -9,223,372,036,854,775,807 to 9,223,372,036,854,775,807.

Remarks
This data type is a 64-bit integer.
You must add an L to the constant definition to inform AL that the integer must be interpreted and treated as a
BigInteger.
If you assign -9,223,372,036,854,775,808 directly to a BigInteger variable, then you get an error when you try to
compile the code. However, you can indirectly assign -9,223,372,036,854,775,808 to a BigInteger variable by
using the following code.

BigIntegerVar := -9223372036854775807L;
BigIntegerVar := BigIntegerVar - 1;

If you try to indirectly assign a value that is smaller than -9,223,372,036,854,775,808, or larger than
9,223,372,036,854,775,807, then you get a run-time error.

Example
BI := 1L;
BI := 455500000000L;

See Also
Get Started with AL
Developing Extensions
Decimal Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Denotes decimal numbers ranging from -999,999,999,999,999.99 to +999,999,999,999,999.99.

Example 1
The following are examples of decimal values.

546.88
3425.57

Example 2
The following is not a decimal, but rather an Integer Data Type.

342

Limits on Decimal Data Type Variables


The Decimal data type is mapped to the Microsoft .NET Framework common language runtime (CLR) Decimal
data type, which controls and the precision and limits for variables.
The following table shows the limits for variables of type Decimal .

L IM IT VA L UE

Maximum format value. +/- 999,999,999,999,999.99

This is the maximum value that can be:

- Formatted into a TEXT variable by the Format function.


- Input from the UI or XMLPorts.
- Assigned directly in source code.

Maximum field data type value. +/- 999,999,999,999,999.99

This is the maximum value that a field variable in a record


can hold while not being persisted.

Maximum persisted value. Can read previous stored values but cannot store values
outside the formatting range since field variables cannot be
This is the maximum value that can be stored in the assigned values outside the formatting range.
database.
L IM IT VA L UE

Maximum calculating value. +/- 79,228,162,514,264,337,593,543,950,335

This is the maximum value that can be calculated by code


statements while not assigning to a field variable, storing to
the database, or formatting to a text variable.

Scaling factor (digits after decimal point) for calculating 28


values
For example, 7.9228162514264337593543950335

The maximum safe value that will work on all Business Central versions of is +/- 999,999,999,999,999.99.
It is possible to assign to a variable the maximum value that can be formatted and then multiply that variable by
a large positive number, thereby generating a greater value. However, we do not recommend doing this. If you
do, you will get errors if you attempt to format this variable to a text variable or assign the variable to a field
variable in a record.

See Also
Get Started with AL
Developing Extensions
BigText Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Handles large text documents.


The following methods are available on instances of the BigText data type.

M ET H O D N A M E DESC RIP T IO N

AddText(Text [, Integer]) Adds a text string to a BigText variable.

AddText(BigText [, Integer]) Adds a text string to a BigText variable.

GetSubText(var Text, Integer [, Integer]) Gets part of a BigText variable.

GetSubText(var BigText, Integer [, Integer]) Gets part of a BigText variable.

Length() Retrieves the length of the text stored in this BigText


instance.

Read(InStream) Streams a BigText object that is stored as a BLOB in a table


to a BigText variable.

TextPos(Text) Gets the position at which a specific string first occurs in this
BigText instance.

Write(OutStream) Streams a BigText object to a BLOB field in a table.

Remarks
This data type cannot be shown in a message window or be seen in the Debugger. The maximum length of a
BigText variable is 2,147,483,647 characters and this corresponds to 2 GB. You can use the BigText methods to
manipulate a BigText variable, for example to extract part of a BigText variable or to add a text string to a BigText
variable. The normal string methods cannot be used with a BigText variable.

See Also
Get Started with AL
Developing Extensions
Byte Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Stores a single, 8-bit character as a value in the range 0 to 255. You can easily convert this data type from a
number to a character and vice versa. This means you can use mathematical operators on Byte variables.

Example
The following example assumes that you have a Byte variable named B and a Text variable named S.
You can assign a constant string of the length 1 to a Byte variable, as shown in the first line of the following code
example. You can assign a single character in a Text or Code variable to a Byte variable, as shown in the second
line of the following code example. You can assign a numeric value to a Byte variable, as shown in the third line
of the following code example. This causes the Byte variable to contain the character from the ASCII character
set that corresponds to the numeric ASCII code.

B := 'A';
B := S[2];
B := 65;

You cannot assign a character to a position greater than the position of the null terminator. For example, if the
value of the text variable MyText is 'abc', then the null terminator is at position 4 and the following assignment
causes a run-time error to occur.

MyText[5] := 'e';

See Also
Get Started with AL
Developing Extensions
Char Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Stores a single, 16-bit character as a value in the range 0 to 65535. You can convert this data type from a
number to a character and vice versa. This means you can use mathematical operators on Char variables.

Example
The following example assumes that you have a Char variable named C and a Text or Code variable named S.
You can assign a constant string of the length 1 to a Char variable, as shown in the first line of the following
code example. You can assign a single Char in a Text or Code variable to a Char variable, as shown in the second
line of the following code example. You can assign a numeric value to a Char variable, as shown in the third line
of the following code example.

C := 'A';
C := S[2];
C := 65;

You cannot assign a Char to a position greater than the position of the null terminator. For example, if the value
of the Text variable MyText is 'abc', then the null terminator is at position 4 and the following assignment causes
a run-time error to occur.

MyText[5] := 'e';

See Also
Get Started with AL
Developing Extensions
Code Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Denotes a special type of string that is converted to uppercase and removes any trailing or leading spaces.

Remarks
The length of a Code variable equals the number of characters in the text without leading or trailing spaces.
You must specify the length of a Code variable or field. The maximum length of a Code variable is 1024
characters. The maximum length of a Code field in a table is 2048 characters. A Code variable cannot be null.
The Code data type supports Unicode.
You can index any character position in a string, such as A[65]. The resulting value will be a Char Data Type. You
cannot assign a char to a position in the code variable greater than the current length of the variable +1.
Fields that contain a date formula must not have data type Code. Instead, use the DateFormula Data Type. All
fields that contain a date formula with data type Code must be converted into data type DateFormula.

Example
This example shows some typical examples of code string assignments. In these examples, assume that the
variable c is a code variable with a maximum length of 4.

c := 'ABC';
// Results in variable c, which contains 'ABC'
// and is 3 characters in length.
c := '1';
// Results in variable c, which contains '1'
// and is 1 character in length.
c := '';
// Results in variable c, which contains '' (empty string)
// and is zero (0) characters in length.
c := ' 2 ';
// Results in variable c, which contains '2'
// and is 1 character in length.

See Also
Get Started with AL
Developing Extensions
Text Data Type
2/6/2023 • 5 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Denotes a text string.


The following methods are available on the Text data type.

M ET H O D N A M E DESC RIP T IO N

ConvertStr(Text, Text, Text) Replaces all chars in source found in FromCharacters with
the corresponding char in ToCharacters and returns the
converted string. If the length of the FromCharacters
parameter and the ToChars parameter are different, an
exception is thrown. If the parameter FromCharacters or the
parameter ToChars is empty, the source is returned
unmodified. Each element in source is only converted ONCE
a double-replacement cannot happen.

CopyStr(Text, Integer [, Integer]) Copies a substring of any length from a specific position in a
string (text or code) to a new string.

DelChr(Text [, Text] [, Text]) Deletes chars contained in the which parameter in a string
based on the contents on the where parameter. If the where
parameter contains an equal-sign, then all occurrences of
characters in which is deleted from the current value. If the
where parameter contains a less-than, then the characters
are only deleted when they are first in the string. If the
where parameter contains a greater-than, then the
characters are only deleted when they are the last in the
string. If the where parameter contains any other char, an
exception is thrown. If the where parameter or the which
parameter is empty, the source is returned unmodified. The
which parameter is to be considered as an array of chars to
delete where the order does not matter.

DelStr(Text, Integer [, Integer]) Deletes a substring inside a string (text or code).

IncStr(Text) Increases a positive number or decrease a negative number


inside a string by one (1).

InsStr(Text, Text, Integer) Inserts a substring into a string.

LowerCase(Text) Converts all letters in a string to lowercase.

MaxStrLen(Text) Gets the maximum defined length of a string variable.

MaxStrLen(Variant) Gets the maximum defined length of a variant variable.


M ET H O D N A M E DESC RIP T IO N

PadStr(Text, Integer [, Text]) Changes the length of a string to a specified length. If the
string is shorter than the specified length, length spaces are
added at the end of the string to match the length. If the
string is longer than the specified length, the string is
truncated. If the specified length is less than 0, an exception
is thrown.

SelectStr(Integer, Text) Retrieves a substring from a comma-separated string.

StrCheckSum(Text [, Text] [, Integer]) Calculates a checksum for a string that contains a number. If
the source is empty, 0 is returned. Each char in the source
and in the weight must be a numeric character 0-9,
otherwise an exception is thrown. If the WeightString
parameter is shorter then the source, it is padded with '1' up
until the length of source. If the WeightString parameter is
longer than the source, an exception is thrown.

StrLen(Text) Gets the length of a string you define.

StrPos(Text, Text) Searches for the first occurrence of substring inside a string.

StrSubstNo(Text [, Any,...]) Replaces %1, %2, %3... and #1, #2, #3... fields in a string with
the values you provide as optional parameters.

UpperCase(Text) Converts all letters in a string to uppercase.

The following methods are available on instances of the Text data type.

M ET H O D N A M E DESC RIP T IO N

Contains(Text) Returns a value indicating whether a specified substring


occurs within this string.

EndsWith(Text) Determines whether the end of this string instance matches


the specified string.

IndexOf(Text [, Integer]) Reports the one-based index of the first occurrence of the
specified string in this instance.

IndexOfAny(Text [, Integer]) Reports the one-based index of the first occurrence of the
specified string in this instance. The search starts at a
specified character position.

IndexOfAny(List of [Char] [, Integer]) Reports the one-based index of the first occurrence in this
instance of any character in a specified array of Unicode
characters. The search starts at a specified character position.

LastIndexOf(Text [, Integer]) Reports the one-based index position of the last occurrence
of a specified string in this instance.

PadLeft(Integer [, Char]) Returns a new Text that right-aligns the characters in this
instance by padding them on the left, for a specified total
length.
M ET H O D N A M E DESC RIP T IO N

PadRight(Integer [, Char]) Returns a new string that left-aligns the characters in this
string by padding them with spaces on the right, for a
specified total length.

Remove(Integer [, Integer]) Returns a new Text in which a specified number of characters


from the current string are deleted.

Replace(Text, Text) Returns a new Text in which all occurrences of a specified


string in the current instance are replaced with another
specified string.

Split([Text,...]) Splits a string into a maximum number of substrings based


on a collection of separators.

Split(List of [Text]) Splits a string into a maximum number of substrings based


on a collection of separators.

Split(List of [Char]) Splits a string into a maximum number of substrings based


on a collection of separators.

StartsWith(Text) Determines whether the beginning of this instance matches


a specified string.

Substring(Integer [, Integer]) Retrieves a substring from this instance.

ToLower() Returns a copy of this string converted to lowercase.

ToUpper() Returns a copy of this string converted to uppercase.

Trim() Returns a new Text in which all leading and trailing white-
space characters from the current Text object are removed.

TrimEnd([Text]) Removes all trailing occurrences of a set of characters


specified in an array from the current Text object.

TrimStart([Text]) Removes all leading occurrences of a set of characters


specified in an array from the current Text object.

Remarks
The Text data type is a value type, such that every time you use a method on it, you create a new string object in
memory. This requires a new allocation of space. In situations where you need to perform repeated
modifications to a string, the overhead associated with creating a Text data type can be costly.
The TextBuilder Data Type is a reference type, which holds a pointer elsewhere in memory. For performance
reasons, we recommend you to use it when you want to modify a string without creating a new object. For
example, using TextBuilder Data Type can boost performance when concatenating many strings together in a
loop.

See Also
Get Started with AL
Developing Extensions
TextBuilder Data Type
TextConst Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Denotes a multi-language string constant.

Remarks
The TextConst data type is typically used for UI messages; process or error messages. Keeping the TextConst
data type in global scope, makes it easier to reuse the same message for several situations. For information
about naming, see CodeCop Rule AA0074.

IMPORTANT
The TextConst data type is not included in the .xlf files for translation. Make sure to use the Label Data Type instead.

Example
The data type can be declared with the syntax as shown in the example below.

codeunit 50100 MyCodeunit


{
procedure MyProcedure()
var
localTextConst: TextConst ENU = 'My text', DAN = 'Min tekst';
begin
Message(localTextConst);
end;

var
globalTextConst: TextConst ENU = 'My text', DAN = 'Min tekst';
}

See Also
Get Started with AL
Developing Extensions
TextBuilder Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents a lighweight wrapper for the .Net implementation of StringBuilder.


The following methods are available on instances of the TextBuilder data type.

M ET H O D N A M E DESC RIP T IO N

Append(Text) Appends a copy of the specified string to this TextBuilder


instance.

AppendLine([Text]) Appends a copy of the specified string followed by the


default line terminator to the end of the current TextBuilder
object. If this parameter is omitted, only the line terminator
will be appended.

Capacity([Integer]) Gets or sets the maximum number of characters that can be


contained in the memory allocated by the current instance.

Clear() Removes all characters from the current TextBuilder instance.

EnsureCapacity(Integer) Ensures that the capacity of this TextBuilder instance is at


least the specified value.

Insert(Integer, Text) Inserts a string into this TextBuilder instance at the specified
character position.

Length([Integer]) Gets or sets the length of this TextBuilder instance.

MaxCapacity() Gets the maximum capacity of this TextBuilder instance.

Remove(Integer, Integer) Removes the specified range of characters from this


TextBuilder instance.

Replace(Text, Text) Replaces all occurrences of a specified string in this


TextBuilder instance with another specified string.

Replace(Text, Text, Integer, Integer) Replaces, within a substring of this instance, all occurrences
of a specified string in this TextBuilder instance with another
specified string.

ToText() Converts the value of this TextBuilder instance to a Text.

ToText(Integer, Integer) Converts the value of a substring of this TextBuilder instance


to a Text.

Remarks
The TextBuilder data type is one-based indexed, that is, the indexing begins with 1.
The Text Data Type is a value type, such that every time you use a method on it, you create a new string object in
memory. This requires a new allocation of space. In situations where you need to perform repeated
modifications to a string, the overhead associated with creating a Text Data Type can be costly.
The TextBuilder data type is a reference type, which holds a pointer elsewhere in memory. For performance
reasons, we recommend you to use it when you want to modify a string without creating a new object. For
example, using TextBuilder data type can boost performance when concatenating many strings together in a
loop.

See Also
Get Started with AL
Developing Extensions
Text Data Type
Boolean Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Indicates true or false.

See Also
Get Started with AL
Developing Extensions
Guid Data Type
2/6/2023 • 3 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents a 16 byte binary data type. This data type is used for the global identification of objects, programs,
records, and so on. The important property of a GUID is that each value is globally unique. The value is
generated by an algorithm, developed by Microsoft, which assures this uniqueness.
The GUID is a 16-byte binary data type that can be logically grouped into the following subgroups:
4byte-2byte-2byte-2byte-6byte.
The standard textual representation is {12345678-1234-1234-1234-1234567890AB}.
The virtual table OLE Control (2000000042) does not use the GUID data type. It uses a textual representation of
the GUID in a text field instead. It is easier to make operations and references to this text field using the GUID
data type than it is using the textual representation. The GUID data type is compatible with the existing textual
representation.
The GUID data type is useful when you want to uniquely identify some data, so that it can be exchanged with
external applications. For example, if you want to transfer an item catalog to an external application, you add a
GUID field to the record in the table and use this as the primary reference when you communicate with the
external application.

Compatibility
You can assign and compare the Text data type and the GUID data type. Assigning a Text to a GUID can be done
as follows:

MyTableRec.MyGuid := MyTableRec.MyText;

The supported formats of MyText are:


'11111111-1111-1111-1111-111111111111' '{22222222-2222-2222-2222-222222222222}'

Methods and properties


The following AL methods can be used with the GUID data type:

Guid := CreateGUID();

This method creates a new unique GUID value. The value can then be assigned to a field of the GUID data type
or of the Text data type.

Ok := IsNullGUID(Guid);

This method is a convenient way to check if a value has already been assigned to a GUID. A NULL GUID
(consisting only of zeroes) is valid, but should never be used for reference purposes.
A NULL GUID is valid but is not useful in a table. Therefore, the AutoSplitKey property is implemented for the
GUID data type when it is used in a page. When GUID is selected as a primary key, AutoSplitKey is enabled for
the page, and the GUID value remains NULL. When you create a new record, a valid GUID is created and
assigned automatically.
The CreateGUID method and IsNullGUID method methods are available in the AL Symbol Menu under SYSTEM,
Variables.
CreateGUID takes no arguments and returns a valid 16-byte GUID value. If the result is assigned to a TEXT
variable or field, the value is converted to a string and follows the syntax explained earlier. The algorithm that
generates the new GUID value uses Microsoft's CoCreateGuid method.
IsNullGUID takes a GUID value as a required argument and returns True/False depending on whether the GUID
value is NULL. This method does not accept a Text value as an argument.
AutoSplitKey is a property, not a method and can be applied to pages. If you have defined a GUID field as part
of the primary key, the AutoSplitKey property automatically generates a new valid GUID value. When a new
record is created and the GUID field is left as NULL, the AutoSplitKey property ensures that a valid GUID value
is automatically inserted into the field. If you then enter a NULL GUID into this record, for example, by using the
Clear method, this new NULL GUID value is not automatically replaced by the AutoSplitKey property. The
AutoSplitKey property only applies to new records.

Format
The GUID value can also be represented as text. You can use the standard AL methods Format and Evaluate to
convert from GUID values to Text values. If you do not use the correct format when you edit a GUID value in its
textual format, the following error message is displayed:
Invalid Format of GUID string. The correct format of the GUID string is {CDEF7890-ABCD-1234-
ABCD-1234567890AB} where 0-9, A-F symbolizes hexadecimal digits.

See Also
Get Started with AL
Developing Extensions
Blob Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Is a complex data type. Variables of this data type differ from normal numeric and string variables in that BLOBs
have a variable length. The maximum size of a BLOB(binary large object) is 2 GB.
The following methods are available on instances of the Blob data type.

M ET H O D N A M E DESC RIP T IO N

CreateInStream(InStream [, TextEncoding]) Creates an InStream object for a binary large object (BLOB).
This enables you to read data from the BLOB.

CreateOutStream(OutStream [, TextEncoding]) Creates an OutStream object for a binary large object


(BLOB). This enables you to write data to the BLOB.

Export(Text) Exports a binary large object (BLOB) to a file.

HasValue() Determines whether a binary large object (BLOB) has a


value.

Import(Text) Imports a binary large object (BLOB) from a file.

Length() Returns the number of bytes in the binary large object


(BLOB).

Remarks
Use BLOBs to store memos (text), pictures (bitmaps), or user-defined types.

NOTE
You cannot view text that is stored in BLOBs from the development environment.

You can read from and write to BLOBs by creating input and output streams, respectively. To do so, use
CreateInStream method (BLOB) and CreateOutStream method (BLOB).

See Also
Get Started with AL
Developing Extensions
Media Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Encapsulates media files, such as image .jpg and .png files, in application database tables. The Media data type
can be used as a table field data type, but cannot be used as a variable or parameter. The Media data type
enables you to import a media file to the application database and reference the file from records, making it
possible to display the media file in the client user interface. You can also export media from the database to
files and streams.
The following methods are available on the Media data type.

M ET H O D N A M E DESC RIP T IO N

FindOrphans() Discovers all orphaned media. Orphaned media is media that


is not referenced by any other table.

The following methods are available on instances of the Media data type.

M ET H O D N A M E DESC RIP T IO N

ExportFile(Text) Exports the media object (such as an image) that is currently


used on record to a file on your computer or network. On
the record, the media object is referenced in a Media data
type field.

ExportStream(OutStream) Exports the current media object (such as a JPEG image) that
is used on record to an OUTSTREAM object. The
OUTSTREAM object can be created from a BLOB field, a FILE
or from a .NET Framework interoperability object. In the
record, the media is referenced in a Media data type field.

HasValue() Checks whether a Media data type field in a record has been
initialized with a media object and that the specified media
object exists in the database.

ImportFile(Text, Text [, Text]) Adds a media type, such as a JPEG image, from a file to a
Media data type field of a record for displaying the media
with the record in the client. The media file is imported to
the application database, and a reference to the media is
included in the Media data type field.

ImportStream(InStream, Text [, Text]) Adds a media type (MIME), such as jpeg image, from an
InStream object to a Media data type field of a record for
displaying the media in the client. The media file is imported
to the application database and a reference to the media is
included in the Media data type field.
M ET H O D N A M E DESC RIP T IO N

ImportStream(InStream, Text, Text, Text) Adds a media type (MIME), such as jpeg image, from an
InStream object to a Media data type field of a record for
displaying the media in the client. The media file is imported
to the application database and a reference to the media is
included in the Media data type field.

MediaId() Gets the unique identifier of a media object on a record.

NOTE
Starting with Business Central 2021 release wave 1, when importing Microsoft Word files (.docx), macro packages (VBA
code) will automatically be removed from the file when stored in the database. If macros are needed for end-user
scenarios, the macro must be in the Word template (.dotx) associated with the document being imported.

See Also
Get Started with AL
Developing Extensions
Working With Media on Records
MediaSet Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Encapsulates media, such as images, in application database tables.


The following methods are available on the MediaSet data type.

M ET H O D N A M E DESC RIP T IO N

FindOrphans() Discovers all orphaned media sets. Orphaned media sets are
media sets that are not referenced by any other table.

The following methods are available on instances of the MediaSet data type.

M ET H O D N A M E DESC RIP T IO N

Count() Gets the number of media objects that are included in the
MediaSet of a record.

ExportFile(Text) Exports the media objects in the current media set of a


record to individual files on your computer or network. In
the record, the media set is referenced in a MediaSet data
type field.

ImportFile(Text, Text [, Text]) Adds a media, such as a JPEG image, to the MediaSet data
type field of a record for displaying the media in the client.
The media is imported to the database and included in a
MediaSet for the record.

ImportStream(InStream, Text [, Text]) Adds a media file, such as a JPEG image, from an InStream
object to the MediaSet of record for displaying in the client.
The media is imported to the database and included in a
MediaSet for the record.

Insert(Guid) Adds a media object that already exists in the database to a


MediaSet of a record.

Item(Integer) Gets the unique identifier (GUID) of a media object that is


assigned to a MediaSet on a record.

MediaId() Gets the unique identifier that is assigned to a MediaSet of a


record. The MediaSet is a collection of media objects that are
used on the record that can be displayed in the client.

Remove(Guid) Removes a media object from a MediaSet of a record.

See Also
Get Started with AL
Developing Extensions
Working With Media on Records
Record Data Type
2/6/2023 • 8 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Is a complex data type.


The following methods are available on instances of the Record data type.

M ET H O D N A M E DESC RIP T IO N

AddLink(Text [, Text]) Adds a link to a record.

AddLoadFields([Any,...]) Specifies fields to be initially loaded when the record is


retrieved from its data source. Subsequent calls to
AddLoadFields will not overwrite fields already selected for
the initial load.

AreFieldsLoaded(Any,...) Checks whether the specified fields are all initially loaded.

Ascending([Boolean]) Gets or sets the order in which the system searches through
a table.

CalcFields(Any [, Any,...]) Calculates the FlowFields in a record. You specify which fields
to calculate by using parameters.

CalcSums(Any [, Any,...]) Calculates the total of a column in a table. You specify which
fields to calculate by using parameters.

ChangeCompany([Text]) Redirects references to table data from one company to


another.

ClearMarks() Removes all the marks from a record.

Consistent(Boolean) Marks a table as being consistent or inconsistent.

Copy(Record [, Boolean]) Copies a specified record's filters, views, automatically


calculated FlowFields, marks, fields, and keys that are
associated with the record from a table or creates a
reference to a record.

CopyFilter(Any, Any) Copies the filter that has been set for one field and applies it
to another field.

CopyFilters(var Record) Copies all the filters set by the SETFILTER method (Record) or
the SETRANGE method (Record) from one record to another.

CopyLinks(var Record) Copies all the links from a specified record.

CopyLinks(RecordRef) Copies all the links from a specified record.


M ET H O D N A M E DESC RIP T IO N

Count() Counts the number of records in a table.

CountApprox() Returns an approximate count of the number of records in


the table, for example, for updating progress bars or
displaying informational messages.

CurrentCompany() Gets the current company of a database table record.

CurrentKey() Gets the current key of a database table.

Delete([Boolean]) Deletes a record in a table.

DeleteAll([Boolean]) Deletes all records in a table that fall within a specified range.

DeleteLink(Integer) Deletes a specified link from a record in a table.

DeleteLinks() Deletes all of the links that have been added to a record.

FieldActive(Any) Checks whether a field is enabled.

FieldCaption(Any) Gets the current caption of the specified field as a string.

FieldError(Any [, Text]) Stops the execution of the code causing a run-time error,
and creates an error message for a field.

FieldError(Any, ErrorInfo) Stops the execution of the code causing a run-time error,
and creates an error message for a field.

FieldName(Any) Gets the name of a field as a string.

FieldNo(Any) Gets the number assigned to a field in the table description.

FilterGroup([Integer]) Gets or sets the filter group that is applied to a table.

Find([Text]) Finds a record in a table that is based on the values stored in


keys.

FindFirst() Finds the first record in a table based on the current key and
filter.

FindLast() Finds the last record in a table based on the current key and
filter.

FindSet([Boolean] [, Boolean]) Finds a set of records in a table based on the current key
and filter.

Get([Any,...]) Gets a record based on values stored in primary key fields.


M ET H O D N A M E DESC RIP T IO N

GetAscending(Any) Gets the sort order for the records returned. You can use
GETASCENDING to identify the sort order of the specified
field because fields can be sorted in ascending or descending
order. For example, you can read data from an ODATA web
service where the data is sorted in ascending order on the
Name field but in descending order on the City field.

GetBySystemId(Guid) Gets a record by its SystemId.

GetFilter(Any) Gets a list of the filters within the current filter group that
are applied to a field.

GetFilters() Gets a string that contains a list of the filters within the
current filter group for all fields in a record. In addition, this
method also returns the state of the MARKEDONLY method
(Record).

GetPosition([Boolean]) Gets a string that contains the primary key of the current
record.

GetRangeMax(Any) Gets the maximum value in a range for a field.

GetRangeMin(Any) Gets the minimum value in a range for a field.

GetView([Boolean]) Gets a string that describes the current sort order, key, and
filters on a table.

HasFilter() Determines whether a filter is attached to a record within the


current filter group.

HasLinks() Determines whether a record contains any links.

Init() Initializes a record in a table.

Insert() Inserts a record into a table without executing the code in


the OnInsert trigger.

Insert(Boolean) Inserts a record into a table.

Insert(Boolean, Boolean) Inserts a record into a table.

IsEmpty() Determines whether a table or a filtered set of records is


empty.

IsTemporary() Determines whether a record refers to a temporary table.

LoadFields(Any,...) Accesses the table's corresponding data source and loads the
values of the specified fields on the record.

LockTable([Boolean] [, Boolean]) Starts locking on a table to protect it from write transactions


that conflict with each other.
M ET H O D N A M E DESC RIP T IO N

Mark([Boolean]) Marks a record. You can also use this method to determine
whether a record is marked.

MarkedOnly([Boolean]) Activates a special filter. After you use this function, your
view of the table includes only records marked by the Mark
(Record) method.

Modify([Boolean]) Modifies a record in a table.

ModifyAll(Any, Any [, Boolean]) Modifies a field in all records within a range that you specify.

Next([Integer]) Steps through a specified number of records and retrieves a


record.

ReadConsistency() Determines if the table supports read consistency.

ReadPermission() Determines whether a user is granted read permission to the


table that contains a record. This method can test for both
full read permission and partial read permission that has
been granted with a security filter.

RecordId() Gets the RecordId of the record that is currently selected in


the table. If no table is selected, an error is generated.

RecordLevelLocking() Determines whether the table supports record-level locking.

Relation(Any) Determines the table relationship of a given field.

Rename(Any [, Any,...]) Changes the value of a primary key in a table.

Reset() Removes all filters, including any special filters set by


MarkedOnly, changes fields select for loading back to all, and
changes the current key to the primary key. Also removes
any marks on the record and clears any AL variables defined
on its table definition.

SecurityFiltering([SecurityFilter]) Gets or sets how security filters are applied to the record.

SetAscending(Any, Boolean) Sets the sort order for the records returned. Use this
method after you have set the keys to sort after, using
SETCURRENTKEY. The default sort order is ascending. You
can use SETASCENDING to change the sort order to
descending for a specific field, while the other fields in the
specified key are sorted in ascending order.

SetAutoCalcFields([Any,...]) Sets the FlowFields that you specify to be automatically


calculated when the record is retrieved from the database.

SetCurrentKey(Any [, Any,...]) Selects a key for a table.

SetFilter(Any, Text [, Any,...]) Assigns a filter to a field that you specify.


M ET H O D N A M E DESC RIP T IO N

SetLoadFields([Any,...]) Sets the fields to be initially loaded when the record is


retrieved from its data source. This will overwrite fields
previously selected for initial load.

SetPermissionFilter() Applies the user's security filter.

SetPosition(Text) Sets the fields in a primary key on a record to the values


specified in the supplied string. The remaining fields are not
changed.

SetRange(Any [, Any] [, Any]) Sets a simple filter, such as a single range or a single value,
on a field.

SetRecFilter() Sets the values in the current key of the current record as a
record filter.

SetView(Text) Sets the current sort order, key, and filters on a table.

TableCaption() Gets the current caption of a table as a string.

TableName() Gets the name of a table.

TestField(Any) Tests that the content of the field is not zero or blank (empty
string).

TestField(Any, ErrorInfo) Tests that the content of the field is not zero or blank (empty
string).

TestField(Any, Boolean) Tests whether the contents of a field match a given value.

TestField(Any, Boolean, ErrorInfo) Tests whether the contents of a field match a given value.

TestField(Any, Integer) Tests whether the contents of a field match a given value.

TestField(Any, Integer, ErrorInfo) Tests whether the contents of a field match a given value.

TestField(Any, BigInteger) Tests whether the contents of a field match a given value.

TestField(Any, BigInteger, ErrorInfo) Tests whether the contents of a field match a given value.

TestField(Any, Decimal) Tests whether the contents of a field match a given value.

TestField(Any, Decimal, ErrorInfo) Tests whether the contents of a field match a given value.

TestField(Any, Guid) Tests whether the contents of a field match a given value.

TestField(Any, Guid, ErrorInfo) Tests whether the contents of a field match a given value.

TestField(Any, Text) Tests whether the contents of a field match a given value.

TestField(Any, Text, ErrorInfo) Tests whether the contents of a field match a given value.
M ET H O D N A M E DESC RIP T IO N

TestField(Any, Label) Tests whether the contents of a field match a given value.

TestField(Any, Label, ErrorInfo) Tests whether the contents of a field match a given value.

TestField(Any, TextConst) Tests whether the contents of a field match a given value.

TestField(Any, TextConst, ErrorInfo) Tests whether the contents of a field match a given value.

TestField(Any, Code) Tests whether the contents of a field match a given value.

TestField(Any, Code, ErrorInfo) Tests whether the contents of a field match a given value.

TestField(Any, Text) Tests whether the contents of a field match a given value.

TestField(Any, Text, ErrorInfo) Tests whether the contents of a field match a given value.

TestField(Any, Enum) Tests whether the contents of a field match a given value.

TestField(Any, Enum, ErrorInfo) Tests whether the contents of a field match a given value.

TestField(Any, Any) Tests whether the contents of a field match a given value.

TestField(Any, Any, ErrorInfo) Tests whether the contents of a field match a given value.

TransferFields(var Record [, Boolean]) Copies all matching fields in one record to another record.

TransferFields(var Record, Boolean, Boolean) Copies all matching fields in one record to another record.

Validate(Any [, Any]) Calls the OnValidate trigger for the field that you specify.

WritePermission() Determines whether a user can write to a table. This method


can test for both full write permission and partial write
permission that has been granted with a security filter. A
write permission consists of Insert, Delete, and Modify
permissions.

See Also
Get Started with AL
Developing Extensions
System Data Type
2/6/2023 • 6 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Is a complex data type.


The following methods are available on the System data type.

M ET H O D N A M E DESC RIP T IO N

Abs(Decimal) Calculates the absolute value of a number (Decimal, Integer


or BigInteger). ABS always returns a positive numeric value
or zero.

ApplicationPath() Returns the path of the directory where the executable file
for the product is installed.

ArrayLen(Array of [Any] [, Integer]) Returns the total number of elements in an array or the
number of elements in a specific dimension.

CalcDate(Text [, Date]) Calculates a new date that is based on a date expression and
a reference date.

CalcDate(DateFormula [, Date]) Calculates a new date that is based on a date expression and
a reference date.

CanLoadType(DotNet) Tests if the specified .NET Framework type can be loaded.

CaptionClassTranslate(Text) Returns a translated version of the caption string. The string


is translated to the current local language.

Clear(var Array of [Any]) Clears the value of a single variable. Also, it clears all the
filters that were set if the variable is a record and resets the
key to the primary key and the company on a record
variable.

Clear(var Any) Clears the value of a single variable. Also, it clears all the
filters that were set if the variable is a record and resets the
key to the primary key and the company on a record
variable.

ClearAll() Clears all internal variables (except REC variables), keys, and
filters in the object and in any associated objects, such as
reports, pages, codeunits, and so on that contain AL code.

ClearCollectedErrors() Clears all collected errors from the current collection scope.

ClearLastError() Removes the last error message from memory.

ClosingDate(Date) Gets the closing date for a Date Data Type.


M ET H O D N A M E DESC RIP T IO N

CodeCoverageInclude(var Record) Includes the code that has been logged.

CodeCoverageLoad() Loads the code that has been logged.

CodeCoverageLog([Boolean] [, Boolean]) Starts and stops the logging of code. You can also use this
method to retrieve the current logging status.

CodeCoverageRefresh() Refreshes the code that has been logged.

CompressArray(Array of [Text]) Moves all non-empty strings (text) in an array to the


beginning of the array. The resulting StringArray has the
same number of elements as the input array, but empty
entries appear at the end of the array.

CopyArray(Array of [Any], Array of [Any], Integer [, Integer]) Copies one or more elements in an array to a new array.

CopyStream(OutStream, InStream [, Integer]) Copies the information that is contained in an InStream to


an OutStream.

CreateDateTime(Date, Time) Creates a DateTime object from a date and a time.

CreateEncryptionKey() Creates an encryption key for the current tenant.

CreateGuid() Creates a new unique GUID. The value can then be assigned
to a GUID data type or a text data type. Use the text data
type if you want to compare the GUID to another text
string.

CurrentDateTime() Gets the current DateTime.

Date2DMY(Date, Integer) Gets the day, month, or year of a Date Data Type.

Date2DWY(Date, Integer) Gets the day of the week, week number, or year of a Date
Data Type.

DaTi2Variant(Date, Time) Creates a variant that contains an encapsulation of a COM


VT\_DATE.

Decrypt(Text) Takes a string as input and returns the decrypted value of


the string.

DeleteEncryptionKey() Deletes an encryption key for the current tenant.

DMY2Date(Integer [, Integer] [, Integer]) Gets a Date object based on a day, month, and year.

DT2Date(DateTime) Gets the date part of a DateTime object.

DT2Time(DateTime) Gets the time part of a DateTime object.

DWY2Date(Integer [, Integer] [, Integer]) Gets a Date that is based on a week day, a week, and a year.
M ET H O D N A M E DESC RIP T IO N

Encrypt(Text) Takes a string as input and returns the encrypted value of


the string.

EncryptionEnabled() Checks if the tenant is configured to allow encryption.

EncryptionKeyExists() Checks whether an encryption key for the current tenant is


present on the server tenant.

Evaluate(var Any, Text [, Integer]) Evaluates a string representation of a value into its typical
representation. The result is assigned to a variable.

ExportEncryptionKey(Text) Returns a password protected temporary filepath containing


the encryption key. When encrypting or decrypting data in
Dynamics 365 Business Central, an encryption key is used. A
single key is used per tenant and every tenant will have a
different key. Keys can be exported to a file which may be
necessary in the case of upgrading or migrating a system
from one set of hardware to another. The
EXPORTENCRYPTIONKEY method allows an administrator to
specify a destination file for the key and specify a password
protection for the file.

ExportObjects(Text, var Record [, Integer]) Exports application objects to a file.

Format(Any [, Integer] [, Integer]) Formats a value into a string.

Format(Any, Integer, Text) Formats a value into a string.

GetCollectedErrors([Boolean]) Gets all collected errors in the current collection scope.

GetDocumentUrl(Guid) Gets the URL for the specified temporary media object ID.

GetDotNetType(Any) Gets the System.Type that corresponds to the given value.

GetLastErrorCallStack() Gets the call stack from where the last error occurred.

GetLastErrorCode() Gets the classification of the last error that occurred.

GetLastErrorObject() Gets the last System.Exception object that occurred.

GetLastErrorText() Gets the last error that occurred in the debugger.

GetLastErrorText(Boolean) Gets the last error that occurred in the debugger.

GetUrl(ClientType [, Text] [, ObjectType] [, Integer] [, Record] [, Generates a URL for the specified client target that is based
Boolean]) on the configuration of the server instance. If the code runs
in a multitenant deployment architecture, the generated URL
will automatically apply to the tenant ID of the current user.

GetUrl(ClientType, Text, ObjectType, Integer, RecordRef [, Generates a URL for the specified client target that is based
Boolean]) on the configuration of the server instance. If the code runs
in a multitenant deployment architecture, the generated URL
will automatically apply to the tenant ID of the current user.
M ET H O D N A M E DESC RIP T IO N

GlobalLanguage([Integer]) Gets and sets the current global language setting.

GuiAllowed() Checks whether the AL code can show any information on


the screen.

HasCollectedErrors() Gets a value indicating whether errors have been collected in


the current error collection scope.

Hyperlink(Text) Passes a URL as an argument to an Internet browser, such as


Windows Internet Explorer.

ImportEncryptionKey(Text, Text) Points to a password protected file that contains the key on
the current server. When encrypting or decrypting data in
Dynamics 365 Business Central, an encryption key is used. A
single key is used per tenant, and every tenant will have a
different key. Keys can be created or imported if one exists
already, as may be the case if upgrading or migrating a
system from one set of hardware to another. The
IMPORTENCRYPTIONKEY method allows an administrator to
specify a file (password protected) which contains a key and
imports it to the current Dynamics 365 Business Central
service.

ImportObjects(Text [, Integer]) Imports application objects from a file.

ImportStreamWithUrlAccess(InStream, Text [, Integer]) Imports an object into a media container to be used in a


temporary URL with a default expiration time.

IsCollectingErrors() Gets a value indicating whether errors are currently being


collected.

IsNull(DotNet) Gets a value indicating whether a DotNet object has been


created or not.

IsNullGuid(Guid) Indicates whether a value has been assigned to a GUID. A


null GUID that consists only of zeros is valid but must never
be used for references.

IsServiceTier() Gets a value indicating whether the runtime is a service tier.

NormalDate(Date) Gets the regular date (instead of the closing date) for the
argument Date.

Power(Decimal, Decimal) Raises a number to a power. For example, you can use this
method to square the number 2 to get the result of 4.

Random(Integer) Returns a pseudo-random number.

Randomize([Integer]) Generates a set of random numbers from which the


RANDOM method (Integer) will select a random number.

Round(Decimal [, Decimal] [, Text]) Rounds the value of a numeric variable.

RoundDateTime(DateTime [, BigInteger] [, Text]) Rounds a DateTime.


M ET H O D N A M E DESC RIP T IO N

Sleep(Integer) Returns control to the operating system for a specified time.

TemporaryPath() Gets the path of the directory where the temporary file is
stored.

Time() Gets the current time from the operating system.

Today() Gets the current date set in the operating system.

Variant2Date(Variant) Gets a date from a variant.

Variant2Time(Variant) Gets a time from a variant.

WindowsLanguage() Gets the current Windows language setting.

WorkDate([Date]) Gets and sets the work date for the current session.

See Also
Get Started with AL
Developing Extensions
JsonArray Data Type
2/6/2023 • 5 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Is a container for any well-formed JSON array. A default JsonArray contains an empty JSON array.
The following methods are available on instances of the JsonArray data type.

M ET H O D N A M E DESC RIP T IO N

Add(JsonToken) Adds a new value at the end of the JsonArray.

Add(JsonArray) Adds a new value at the end of the JsonArray.

Add(JsonObject) Adds a new value at the end of the JsonArray.

Add(JsonValue) Adds a new value at the end of the JsonArray.

Add(Boolean) Adds a new value at the end of the JsonArray.

Add(Char) Adds a new value at the end of the JsonArray.

Add(Byte) Adds a new value at the end of the JsonArray.

Add(Option) Adds a new value at the end of the JsonArray.

Add(Integer) Adds a new value at the end of the JsonArray.

Add(BigInteger) Adds a new value at the end of the JsonArray.

Add(Decimal) Adds a new value at the end of the JsonArray.

Add(Duration) Adds a new value at the end of the JsonArray.

Add(Date) Adds a new value at the end of the JsonArray.

Add(Time) Adds a new value at the end of the JsonArray.

Add(DateTime) Adds a new value at the end of the JsonArray.

Add(Text) Adds a new value at the end of the JsonArray.

AsToken() Converts the value in a JsonArray to a JsonToken data type.

Clone() Creates a deep-copy of the JsonArray value.

Count() Gets the number of elements in the JsonArray.


M ET H O D N A M E DESC RIP T IO N

Get(Integer, var JsonToken) Retrieves the value at the given index in the JsonArray.

IndexOf(JsonToken) Determines the index of a specific value in the JsonArray.

IndexOf(JsonArray) Determines the index of a specific value in the JsonArray.

IndexOf(JsonObject) Determines the index of a specific value in the JsonArray.

IndexOf(JsonValue) Determines the index of a specific value in the JsonArray.

IndexOf(Boolean) Determines the index of a specific value in the JsonArray.

IndexOf(Char) Determines the index of a specific value in the JsonArray.

IndexOf(Byte) Determines the index of a specific value in the JsonArray.

IndexOf(Option) Determines the index of a specific value in the JsonArray.

IndexOf(Integer) Determines the index of a specific value in the JsonArray.

IndexOf(BigInteger) Determines the index of a specific value in the JsonArray.

IndexOf(Decimal) Determines the index of a specific value in the JsonArray.

IndexOf(Duration) Determines the index of a specific value in the JsonArray.

IndexOf(Date) Determines the index of a specific value in the JsonArray.

IndexOf(Time) Determines the index of a specific value in the JsonArray.

IndexOf(DateTime) Determines the index of a specific value in the JsonArray.

IndexOf(Text) Determines the index of a specific value in the JsonArray.

Insert(Integer, JsonToken) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, JsonArray) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, JsonObject) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, JsonValue) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, Boolean) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, Char) Inserts the value at the given index in the array while
shifting all the values to the right by one position.
M ET H O D N A M E DESC RIP T IO N

Insert(Integer, Byte) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, Option) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, Integer) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, BigInteger) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, Decimal) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, Duration) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, Date) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, Time) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, DateTime) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Insert(Integer, Text) Inserts the value at the given index in the array while
shifting all the values to the right by one position.

Path() Retrieves the JSON path of the array relative to the root of
its containing tree.

ReadFrom(Text) Reads the JSON data from the string into a JsonArray
variable.

ReadFrom(InStream) Reads the JSON data from the stream into a JsonArray
variable.

RemoveAt(Integer) Removes the token at the given index.

SelectToken(Text, var JsonToken) Selects a JsonToken using a JPath expression.

Set(Integer, JsonToken) Replaces the value at the given index with a new value.

Set(Integer, JsonObject) Replaces the value at the given index with a new value.

Set(Integer, JsonArray) Replaces the value at the given index with a new value.

Set(Integer, JsonValue) Replaces the value at the given index with a new value.

Set(Integer, Boolean) Replaces the value at the given index with a new value.
M ET H O D N A M E DESC RIP T IO N

Set(Integer, Char) Replaces the value at the given index with a new value.

Set(Integer, Byte) Replaces the value at the given index with a new value.

Set(Integer, Option) Replaces the value at the given index with a new value.

Set(Integer, Integer) Replaces the value at the given index with a new value.

Set(Integer, BigInteger) Replaces the value at the given index with a new value.

Set(Integer, Decimal) Replaces the value at the given index with a new value.

Set(Integer, Duration) Replaces the value at the given index with a new value.

Set(Integer, Date) Replaces the value at the given index with a new value.

Set(Integer, Time) Replaces the value at the given index with a new value.

Set(Integer, DateTime) Replaces the value at the given index with a new value.

Set(Integer, Text) Replaces the value at the given index with a new value.

WriteTo(var Text) Serializes and writes the JSON data of the JsonArray to a
given Text object.

WriteTo(OutStream) Serializes and writes the JSON data of the JsonArray to a


given OutStream object.

NOTE
For performance reasons all HTTP, JSON, TextBuilder, and XML types are reference types, not value types. Reference types
holds a pointer to the data elsewhere in memory, whereas value types store its own data.

NOTE
The JsonArray is 0-based by design.

See Also
Get Started with AL
Developing Extensions
JsonObject Data Type
2/6/2023 • 3 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Is a container for any well-formed JSON object. A default JsonObject contains an empty JSON object.
The following methods are available on instances of the JsonObject data type.

M ET H O D N A M E DESC RIP T IO N

Add(Text, JsonToken) Adds a new property to a JsonObject.

Add(Text, JsonObject) Adds a new property to a JsonObject.

Add(Text, JsonValue) Adds a new property to a JsonObject.

Add(Text, JsonArray) Adds a new property to a JsonObject.

Add(Text, Boolean) Adds a new property to a JsonObject.

Add(Text, Char) Adds a new property to a JsonObject.

Add(Text, Byte) Adds a new property to a JsonObject.

Add(Text, Option) Adds a new property to a JsonObject.

Add(Text, Integer) Adds a new property to a JsonObject.

Add(Text, BigInteger) Adds a new property to a JsonObject.

Add(Text, Decimal) Adds a new property to a JsonObject.

Add(Text, Duration) Adds a new property to a JsonObject.

Add(Text, Text) Adds a new property to a JsonObject.

Add(Text, Date) Adds a new property to a JsonObject.

Add(Text, Time) Adds a new property to a JsonObject.

Add(Text, DateTime) Adds a new property to a JsonObject.

AsToken() Converts the value in a JsonObject to a JsonToken data type.

Clone() Creates a deep-copy of the JsonToken value.

Contains(Text) Verifies if a JsonObject contains a property with a given key.


M ET H O D N A M E DESC RIP T IO N

Get(Text, var JsonToken) Retrieves the value of a property with a given key from a
JsonObject.

Keys() Gets a set of keys of the JsonObject.

Path() Retrieves the JSON path of the object relative to the root of
its containing tree.

ReadFrom(Text) Reads the JSON data from the string into a JsonObject
variable.

ReadFrom(InStream) Reads the JSON data from the stream into a JsonObject
variable.

Remove(Text) Removes the property with the given key from the object.

Replace(Text, JsonToken) Replaces the value of the property with the given key with
the new value.

Replace(Text, JsonArray) Replaces the value of the property with the given key with
the new value.

Replace(Text, JsonObject) Replaces the value of the property with the given key with
the new value.

Replace(Text, JsonValue) Replaces the value of the property with the given key with
the new value.

Replace(Text, Boolean) Replaces the value of the property with the given key with
the new value.

Replace(Text, Char) Replaces the value of the property with the given key with
the new value.

Replace(Text, Byte) Replaces the value of the property with the given key with
the new value.

Replace(Text, Integer) Replaces the value of the property with the given key with
the new value.

Replace(Text, Option) Replaces the value of the property with the given key with
the new value.

Replace(Text, BigInteger) Replaces the value of the property with the given key with
the new value.

Replace(Text, Decimal) Replaces the value of the property with the given key with
the new value.

Replace(Text, Duration) Replaces the value of the property with the given key with
the new value.
M ET H O D N A M E DESC RIP T IO N

Replace(Text, Date) Replaces the value of the property with the given key with
the new value.

Replace(Text, Time) Replaces the value of the property with the given key with
the new value.

Replace(Text, DateTime) Replaces the value of the property with the given key with
the new value.

Replace(Text, Text) Replaces the value of the property with the given key with
the new value.

SelectToken(Text, var JsonToken) Selects a JsonToken using a JPath expression.

Values() Gets a set of values of the JsonObject.

WriteTo(var Text) Serializes and writes the JSON data of the JsonObject to a
given Text object.

WriteTo(OutStream) Serializes and writes the JSON data of the JsonObject to a


given OutStream object.

NOTE
For performance reasons all HTTP, JSON, TextBuilder, and XML types are reference types, not value types. Reference types
holds a pointer to the data elsewhere in memory, whereas value types store its own data.

Remarks
An unitialized variable of JsonObject type represents an empty JSON object. Given a value of JsonObject type,
you can check if it is empty by checking that the number of keys in the object is 0.

jsonObject.Keys.Count = 0

See Also
Get Started with AL
Developing Extensions
JsonToken Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Is a container for any well-formed JSON data. A default JsonToken object contains the JSON value of NULL.
The following methods are available on instances of the JsonToken data type.

M ET H O D N A M E DESC RIP T IO N

AsArray() Converts the value in a JsonToken to a JsonArray data type.

AsObject() Converts the value in a JsonToken to a JsonObject data type.

AsValue() Converts the value in a JsonToken to a JsonValue data type.

Clone() Creates a deep-copy of the JsonToken value.

IsArray() Indicates whether a JsonToken represents a JSON array.

IsObject() Indicates whether a JsonToken contains a JSON object.

IsValue() Indicates whether a JsonToken contains a JSON value.

Path() Retrieves the JSON path of the token relative to the root of
its containing tree.

ReadFrom(Text) Reads the JSON data from the string into a JsonToken
variable.

ReadFrom(InStream) Reads the JSON data from the stream into a JsonToken
variable.

SelectToken(Text, var JsonToken) Selects a JsonToken using a JPath expression.

WriteTo(var Text) Serializes and writes the JSON data of the JsonToken to a
given Text object.

WriteTo(OutStream) Serializes and writes the JSON data of the JsonToken to a


given OutStream object.

NOTE
For performance reasons all HTTP, JSON, TextBuilder, and XML types are reference types, not value types. Reference types
holds a pointer to the data elsewhere in memory, whereas value types store its own data.

See Also
Get Started with AL
Developing Extensions
JsonValue Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Is a container for any well-formed fundamental JSON value. A default JsonValue is set to the JSON value of
NULL.
The following methods are available on instances of the JsonValue data type.

M ET H O D N A M E DESC RIP T IO N

AsBigInteger() Converts the value in a JsonValue to an BigInteger data


type.

AsBoolean() Converts the value in a JsonValue to a Boolean data type.

AsByte() Converts the value in a JsonValue to a Byte data type.

AsChar() Converts the value in a JsonValue to a Char data type.

AsCode() Converts the value in a JsonValue to a Code data type.

AsDate() Converts the value in a JsonValue to a Date data type.

AsDateTime() Converts the value in a JsonValue to a DateTime data type.

AsDecimal() Converts the value in a JsonValue to a Decimal data type.

AsDuration() Converts the value in a JsonValue to a Duration data type.

AsInteger() Converts the value in a JsonValue to an Integer data type.

AsOption() Converts the value in a JsonValue to an Option data type.

AsText() Converts the value in a JsonValue to a Text data type.

AsTime() Converts the value in a JsonValue to a Time data type.

AsToken() Converts the value in a JsonValue to a JsonToken data type.

Clone() Creates a deep-copy of the JsonToken value.

IsNull() Indicates whether the JsonValue contains the JSON value of


NULL.

IsUndefined() Indicates whether the JsonValue contains the JSON value of


UNDEFINED.
M ET H O D N A M E DESC RIP T IO N

Path() Retrieves the JSON path of the value relative to its


containing tree.

ReadFrom(Text) Reads the JSON data into a JsonValue variable.

ReadFrom(InStream) Reads the JSON data from the stream into a JsonValue
variable.

SelectToken(Text, var JsonToken) Selects a JsonToken using a JPath expression.

SetValue(Boolean) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValue(Char) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValue(Byte) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValue(Option) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValue(Integer) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValue(BigInteger) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValue(Decimal) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValue(Duration) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValue(Date) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValue(Time) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValue(DateTime) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValue(Text) Set the contents of the JsonValue variable to the JSON


representation of the given value.

SetValueToNull() Set the contents of the JsonValue variable to the JSON


representation of NULL.

SetValueToUndefined() Set the contents of the JsonValue variable to the JSON


representation of UNDEFINED.
M ET H O D N A M E DESC RIP T IO N

WriteTo(var Text) Serializes and writes the JSON data of the JsonValue to a
given object.

WriteTo(OutStream) Serializes and writes the JSON data of the JsonValue to a


given object.

NOTE
For performance reasons all HTTP, JSON, TextBuilder, and XML types are reference types, not value types. Reference types
holds a pointer to the data elsewhere in memory, whereas value types store its own data.

See Also
Get Started with AL
Developing Extensions
XmlAttribute Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents an XML attribute.


The following methods are available on the XmlAttribute data type.

M ET H O D N A M E DESC RIP T IO N

Create(Text, Text) Creates an XmlAttribute node.

Create(Text, Text, Text) Creates an XmlAttribute node.

CreateNamespaceDeclaration(Text, Text) Creates an attribute that represents a namespace


declaration.

The following methods are available on instances of the XmlAttribute data type.

M ET H O D N A M E DESC RIP T IO N

AddAfterSelf(Any,...) Adds the specified content immediately after this node.

AddBeforeSelf(Any,...) Adds the specified content immediately before this node.

AsXmlNode() Converts the node to an XmlNode.

GetDocument(var XmlDocument) Gets the XmlDocument for this node.

GetParent(var XmlElement) Gets the parent XmlElement of this node.

IsNamespaceDeclaration() Determines if this attribute is a namespace declaration.

LocalName() Gets the local name of the attribute.

Name() The qualified name of the attribute.

NamespacePrefix() Gets the prefix of the attribute (if any).

NamespaceUri() Gets the namespace URI of the attribute.

Remove() Removes this node from its parent element.

ReplaceWith(Any,...) Replaces this node with the specified content.

SelectNodes(Text, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectNodes(Text, XmlNamespaceManager, var XmlNodeList) Selects a list of nodes matching the XPath expression.
M ET H O D N A M E DESC RIP T IO N

SelectSingleNode(Text, var XmlNode) Selects the first XmlNode that matches the XPath expression.

SelectSingleNode(Text, XmlNamespaceManager, var Selects the first XmlNode that matches the XPath expression.
XmlNode)

Value([Text]) Gets or sets the value of the attribute.

WriteTo(OutStream) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, OutStream) Serializes and saves the current node to the given variable.

WriteTo(var Text) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, var Text) Serializes and saves the current node to the given variable.

See Also
Get Started with AL
Developing Extensions
XmlAttributeCollection Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents a collection of XML attributes.


The following methods are available on instances of the XmlAttributeCollection data type.

M ET H O D N A M E DESC RIP T IO N

Count() Gets the number of attributes in the XmlAttributeCollection.

Get(Integer, var XmlAttribute) Gets the specified attribute.

Get(Text, var XmlAttribute) Gets the specified attribute.

Get(Text, Text, var XmlAttribute) Gets the specified attribute.

Remove(XmlAttribute) Removes the specified attribute from the collection.

Remove(Text) Removes the specified attribute from the collection.

Remove(Text, Text) Removes the specified attribute from the collection.

RemoveAll() Removes all attributes from the collection.

Set(Text, Text) Sets the value of the specified attribute or creates it if is not
part of the collection.

Set(Text, Text, Text) Sets the value of the specified attribute or creates it if is not
part of the collection.

See Also
Get Started with AL
Developing Extensions
XmlCData Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents a CData section.


The following methods are available on the XmlCData data type.

M ET H O D N A M E DESC RIP T IO N

Create(Text) Creates an XmlCData node.

The following methods are available on instances of the XmlCData data type.

M ET H O D N A M E DESC RIP T IO N

AddAfterSelf(Any,...) Adds the specified content immediately after this node.

AddBeforeSelf(Any,...) Adds the specified content immediately before this node.

AsXmlNode() Converts the node to an XmlNode.

GetDocument(var XmlDocument) Gets the XmlDocument for this node.

GetParent(var XmlElement) Gets the parent XmlElement of this node.

Remove() Removes this node from its parent element.

ReplaceWith(Any,...) Replaces this node with the specified content.

SelectNodes(Text, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectNodes(Text, XmlNamespaceManager, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectSingleNode(Text, var XmlNode) Selects the first XmlNode that matches the XPath expression.

SelectSingleNode(Text, XmlNamespaceManager, var Selects the first XmlNode that matches the XPath expression.
XmlNode)

Value([Text]) Gets or sets the value of this node.

WriteTo(OutStream) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, OutStream) Serializes and saves the current node to the given variable.

WriteTo(var Text) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, var Text) Serializes and saves the current node to the given variable.
See Also
Get Started with AL
Developing Extensions
XmlComment Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents an XML comment.


The following methods are available on the XmlComment data type.

M ET H O D N A M E DESC RIP T IO N

Create(Text) Creates an XmlComment node.

The following methods are available on instances of the XmlComment data type.

M ET H O D N A M E DESC RIP T IO N

AddAfterSelf(Any,...) Adds the specified content immediately after this node.

AddBeforeSelf(Any,...) Adds the specified content immediately before this node.

AsXmlNode() Converts the node to an XmlNode.

GetDocument(var XmlDocument) Gets the XmlDocument for this node.

GetParent(var XmlElement) Gets the parent XmlElement of this node.

Remove() Removes this node from its parent element.

ReplaceWith(Any,...) Replaces this node with the specified content.

SelectNodes(Text, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectNodes(Text, XmlNamespaceManager, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectSingleNode(Text, var XmlNode) Selects the first XmlNode that matches the XPath expression.

SelectSingleNode(Text, XmlNamespaceManager, var Selects the first XmlNode that matches the XPath expression.
XmlNode)

Value([Text]) Gets or sets the string value of this comment.

WriteTo(OutStream) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, OutStream) Serializes and saves the current node to the given variable.

WriteTo(var Text) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, var Text) Serializes and saves the current node to the given variable.
See Also
Get Started with AL
Developing Extensions
XmlDeclaration Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents an XML declaration.


The following methods are available on the XmlDeclaration data type.

M ET H O D N A M E DESC RIP T IO N

Create(Text, Text, Text) Creates an XmlDeclaration node.

The following methods are available on instances of the XmlDeclaration data type.

M ET H O D N A M E DESC RIP T IO N

AddAfterSelf(Any,...) Adds the specified content immediately after this node.

AddBeforeSelf(Any,...) Adds the specified content immediately before this node.

AsXmlNode() Converts the node to an XmlNode.

Encoding([Text]) Gets or sets the encoding of the XML document.

GetDocument(var XmlDocument) Gets the XmlDocument for this node.

GetParent(var XmlElement) Gets the parent XmlElement of this node.

Remove() Removes this node from its parent element.

ReplaceWith(Any,...) Replaces this node with the specified content.

SelectNodes(Text, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectNodes(Text, XmlNamespaceManager, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectSingleNode(Text, var XmlNode) Selects the first XmlNode that matches the XPath expression.

SelectSingleNode(Text, XmlNamespaceManager, var Selects the first XmlNode that matches the XPath expression.
XmlNode)

Standalone([Text]) Gets or sets the standalone property for this document.

Version([Text]) Gets or sets the version property for this document.

WriteTo(OutStream) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, OutStream) Serializes and saves the current node to the given variable.
M ET H O D N A M E DESC RIP T IO N

WriteTo(var Text) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, var Text) Serializes and saves the current node to the given variable.

See Also
Get Started with AL
Developing Extensions
XmlDocument Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents an XML document.


The following methods are available on the XmlDocument data type.

M ET H O D N A M E DESC RIP T IO N

Create() Creates an XmlDocument.

Create(Any,...) Creates an XmlDocument.

ReadFrom(Text, var XmlDocument) Reads and parses the XML document from the given data
source.

ReadFrom(Text, XmlReadOptions, var XmlDocument) Reads and parses the XML document from the given data
source.

ReadFrom(InStream, var XmlDocument) Reads and parses the XML document from the given data
source.

ReadFrom(InStream, XmlReadOptions, var XmlDocument) Reads and parses the XML document from the given data
source.

The following methods are available on instances of the XmlDocument data type.

M ET H O D N A M E DESC RIP T IO N

Add(Any,...) Adds the specified content as a child of this document.

AddAfterSelf(Any,...) Adds the specified content immediately after this node.

AddBeforeSelf(Any,...) Adds the specified content immediately before this node.

AddFirst(Any,...) Adds the specified content at the start of the child list of this
document.

AsXmlNode() Converts the node to an XmlNode.

GetChildElements() Gets a list containing the child elements for this document,
in document order.

GetChildElements(Text) Gets a list containing the child elements for this document,
in document order.

GetChildElements(Text, Text) Gets a list containing the child elements for this document,
in document order.
M ET H O D N A M E DESC RIP T IO N

GetChildNodes() Gets a list containing the child elements for this document,
in document order.

GetDeclaration(var XmlDeclaration) Gets the XML declaration for this document.

GetDescendantElements() Gets a list containing the descendant elements for this


document, in document order.

GetDescendantElements(Text) Gets a list containing the descendant elements for this


document, in document order.

GetDescendantElements(Text, Text) Gets a list containing the descendant elements for this
document, in document order.

GetDescendantNodes() Gets a list containing the descendant nodes for this


document, in document order.

GetDocument(var XmlDocument) Gets the XmlDocument for this node.

GetDocumentType(var XmlDocumentType) Gets the Document Type Definition (DTD) for this document.

GetParent(var XmlElement) Gets the parent XmlElement of this node.

GetRoot(var XmlElement) Gets the root element of the XML tree for this document.

NameTable() Gets the XmlNameTable associated with this document.

Remove() Removes this node from its parent element.

RemoveNodes() Removes the child nodes from this document.

ReplaceNodes(Any,...) Replaces the children nodes of this document with the


specified content.

ReplaceWith(Any,...) Replaces this node with the specified content.

SelectNodes(Text, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectNodes(Text, XmlNamespaceManager, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectSingleNode(Text, var XmlNode) Selects the first XmlNode that matches the XPath expression.

SelectSingleNode(Text, XmlNamespaceManager, var Selects the first XmlNode that matches the XPath expression.
XmlNode)

SetDeclaration(XmlDeclaration) Sets the XML declaration for this document.

WriteTo(OutStream) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, OutStream) Serializes and saves the current node to the given variable.
M ET H O D N A M E DESC RIP T IO N

WriteTo(var Text) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, var Text) Serializes and saves the current node to the given variable.

See Also
Get Started with AL
Developing Extensions
XmlDocumentType Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents an XML document type.


The following methods are available on the XmlDocumentType data type.

M ET H O D N A M E DESC RIP T IO N

Create(Text) Creates an XmlDocumentType node.

Create(Text, Text) Creates an XmlDocumentType node.

Create(Text, Text, Text) Creates an XmlDocumentType node.

Create(Text, Text, Text, Text) Creates an XmlDocumentType node.

The following methods are available on instances of the XmlDocumentType data type.

M ET H O D N A M E DESC RIP T IO N

AddAfterSelf(Any,...) Adds the specified content immediately after this node.

AddBeforeSelf(Any,...) Adds the specified content immediately before this node.

AsXmlNode() Converts the node to an XmlNode.

GetDocument(var XmlDocument) Gets the XmlDocument for this node.

GetInternalSubset(var Text) Gets the internal subset for this Document Type Definition
(DTD).

GetName(var Text) Gets the name for this Document Type Definition (DTD).

GetParent(var XmlElement) Gets the parent XmlElement of this node.

GetPublicId(var Text) Gets the public identifier for this Document Type Definition
(DTD).

GetSystemId(var Text) Gets the system identifier for this Document Type Definition
(DTD).

Remove() Removes this node from its parent element.

ReplaceWith(Any,...) Replaces this node with the specified content.

SelectNodes(Text, var XmlNodeList) Selects a list of nodes matching the XPath expression.
M ET H O D N A M E DESC RIP T IO N

SelectNodes(Text, XmlNamespaceManager, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectSingleNode(Text, var XmlNode) Selects the first XmlNode that matches the XPath expression.

SelectSingleNode(Text, XmlNamespaceManager, var Selects the first XmlNode that matches the XPath expression.
XmlNode)

SetInternalSubset(Text) Sets the internal subset for this Document Type Definition
(DTD).

SetName(Text) Sets the name for this Document Type Definition (DTD).

SetPublicId(Text) Sets the public identifier for this Document Type Definition
(DTD).

SetSystemId(Text) Sets the system identifier for this Document Type Definition
(DTD).

WriteTo(OutStream) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, OutStream) Serializes and saves the current node to the given variable.

WriteTo(var Text) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, var Text) Serializes and saves the current node to the given variable.

See Also
Get Started with AL
Developing Extensions
XmlElement Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents an XML element.


The following methods are available on the XmlElement data type.

M ET H O D N A M E DESC RIP T IO N

Create(Text) Creates an XmlElement node.

Create(Text, Text) Creates an XmlElement node.

Create(Text, Text, Any,...) Creates an XmlElement node.

Create(Text, Any,...) Creates an XmlElement node.

The following methods are available on instances of the XmlElement data type.

M ET H O D N A M E DESC RIP T IO N

Add(Any,...) Adds the specified content as a child of this element.

AddAfterSelf(Any,...) Adds the specified content immediately after this node.

AddBeforeSelf(Any,...) Adds the specified content immediately before this node.

AddFirst(Any,...) Adds the specified content at the start of the child list of this
element.

AsXmlNode() Converts the node to an XmlNode.

Attributes() Gets a collection of the attributes of this element.

GetChildElements() Gets a list containing the child elements for this element, in
document order.

GetChildElements(Text) Gets a list containing the child elements for this element, in
document order.

GetChildElements(Text, Text) Gets a list containing the child elements for this element, in
document order.

GetChildNodes() Gets a list containing the child elements for this element, in
document order.

GetDescendantElements() Gets a list containing the descendant elements for this


element, in document order.
M ET H O D N A M E DESC RIP T IO N

GetDescendantElements(Text) Gets a list containing the descendant elements for this


element, in document order.

GetDescendantElements(Text, Text) Gets a list containing the descendant elements for this
element, in document order.

GetDescendantNodes() Gets a list containing the descendant nodes for this element,
in document order.

GetDocument(var XmlDocument) Gets the XmlDocument for this node.

GetNamespaceOfPrefix(Text, var Text) Gets the namespace associated with a particular prefix for
this element.

GetParent(var XmlElement) Gets the parent XmlElement of this node.

GetPrefixOfNamespace(Text, var Text) Gets the prefix associated with a namespace URI for this
element.

HasAttributes() Gets a boolean value indicating whether this element has at


least one attribute.

HasElements() Gets a value indicating whether this element has at least one
child element.

InnerText() Gets the concatenated values of the node and all its child
nodes.

InnerXml() Gets the markup representing only the child nodes of this
node.

IsEmpty() Gets a value indicating whether this element contains no


content.

LocalName() Gets the local name of this element.

Name() Gets the fully qualified name of this element.

NamespaceUri() Gets the namespace URI of this element.

Remove() Removes this node from its parent element.

RemoveAllAttributes() Removes the attributes of this element.

RemoveAttribute(Text) Removes the specified attribute from this element.

RemoveAttribute(Text, Text) Removes the specified attribute from this element.

RemoveAttribute(XmlAttribute) Removes the specified attribute from this element.

RemoveNodes() Removes the child nodes from this element.


M ET H O D N A M E DESC RIP T IO N

ReplaceNodes(Any,...) Replaces the children nodes of this element with the


specified content.

ReplaceWith(Any,...) Replaces this node with the specified content.

SelectNodes(Text, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectNodes(Text, XmlNamespaceManager, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectSingleNode(Text, var XmlNode) Selects the first XmlNode that matches the XPath expression.

SelectSingleNode(Text, XmlNamespaceManager, var Selects the first XmlNode that matches the XPath expression.
XmlNode)

SetAttribute(Text, Text) Sets the value of the specified attribute or create it if is not
part of the element's attribute collection.

SetAttribute(Text, Text, Text) Sets the value of the specified attribute or create it if is not
part of the element's attribute collection.

WriteTo(OutStream) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, OutStream) Serializes and saves the current node to the given variable.

WriteTo(var Text) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, var Text) Serializes and saves the current node to the given variable.

See Also
Get Started with AL
Developing Extensions
XmlNamespaceManager Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents a namespace manager that can be used to resolve, add and remove namespaces to a collection. It
also provides scope management for these namespaces.
The following methods are available on instances of the XmlNamespaceManager data type.

M ET H O D N A M E DESC RIP T IO N

AddNamespace(Text, Text) Adds the given namespace to the collection.

HasNamespace(Text) Gets a value indicating whether the supplied prefix has a


namespace defined for the current scope.

LookupNamespace(Text, var Text) Gets the namespace URI for the specified prefix.

LookupPrefix(Text, var Text) Finds the prefix declared for the given namespace URI.

NameTable([XmlNameTable]) Gets or sets the XmlNameTable associated with this object.

PopScope() Pops a namespace scope off the stack.

PushScope() Pushes a namespace scope onto the stack.

RemoveNamespace(Text, Text) Removes the given namespace for the given prefix.

See Also
Get Started with AL
Developing Extensions
XmlNameTable Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents a table of atomized string objects.


The following methods are available on instances of the XmlNameTable data type.

M ET H O D N A M E DESC RIP T IO N

Add(Text) Atomizes the specified string and adds it to the


XmlNameTable.

Get(Text, var Text) Gets the atomized string with the specified value.

See Also
Get Started with AL
Developing Extensions
XmlNode Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents a XML node which can either be for instance an XML attribute, an XML element or a XML document.
The following methods are available on instances of the XmlNode data type.

M ET H O D N A M E DESC RIP T IO N

AddAfterSelf(Any,...) Adds the specified content immediately after this node.

AddBeforeSelf(Any,...) Adds the specified content immediately before this node.

AsXmlAttribute() Converts the node to an XmlAttribute node. The operation


will fail if the node is not an XmlAttribute.

AsXmlCData() Converts the node to an XmlCData node. The operation will


fail if the node is not an XmlCData.

AsXmlComment() Converts the node to an XmlComment node. The operation


will fail if the node is not an XmlComment.

AsXmlDeclaration() Converts the node to an XmlDeclaration node. The


operation will fail if the node is not an XmlDeclaration.

AsXmlDocument() Converts the node to an XmlDocument node. The operation


will fail if the node is not an XmlDocument.

AsXmlDocumentType() Converts the node to an XmlDocumentType node. The


operation will fail if the node is not an XmlDocumentType.

AsXmlElement() Converts the node to an XmlElement node. The operation


will fail if the node is not an XmlElement.

AsXmlProcessingInstruction() Converts the node to an XmlProcessingInstruction node.


The operation will fail if the node is not an
XmlProcessingInstruction.

AsXmlText() Converts the node to an XmlText node. The operation will fail
if the node is not an XmlText.

GetDocument(var XmlDocument) Gets the XmlDocument for this node.

GetParent(var XmlElement) Gets the parent XmlElement of this node.

IsXmlAttribute() Gets a value indicating whether this node is an XmlAttribute.

IsXmlCData() Gets a value indicating whether this node is an XmlCData.


M ET H O D N A M E DESC RIP T IO N

IsXmlComment() Gets a value indicating whether this node is an


XmlComment.

IsXmlDeclaration() Gets a value indicating whether this node is an


XmlDeclaration.

IsXmlDocument() Gets a value indicating whether this node is an


XmlDocument.

IsXmlDocumentType() Gets a value indicating whether this node is an


XmlDocumentType.

IsXmlElement() Gets a value indicating whether this node is an XmlElement.

IsXmlProcessingInstruction() Gets a value indicating whether this node is an


XmlProcessingInstruction.

IsXmlText() Gets a value indicating whether this node is an XmlText.

Remove() Removes this node from its parent element.

ReplaceWith(Any,...) Replaces this node with the specified content.

SelectNodes(Text, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectNodes(Text, XmlNamespaceManager, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectSingleNode(Text, var XmlNode) Selects the first XmlNode that matches the XPath expression.

SelectSingleNode(Text, XmlNamespaceManager, var Selects the first XmlNode that matches the XPath expression.
XmlNode)

WriteTo(OutStream) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, OutStream) Serializes and saves the current node to the given variable.

WriteTo(var Text) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, var Text) Serializes and saves the current node to the given variable.

See Also
Get Started with AL
Developing Extensions
XmlNodeList Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents a collection of XML nodes.


The following methods are available on instances of the XmlNodeList data type.

M ET H O D N A M E DESC RIP T IO N

Count() Gets the number of nodes in the XmlNodeList.

Get(Integer, var XmlNode) Gets a node at the given index.

See Also
Get Started with AL
Developing Extensions
XmlText Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents the text content of an element or attribute.


The following methods are available on the XmlText data type.

M ET H O D N A M E DESC RIP T IO N

Create(Text) Creates an XmlText node.

The following methods are available on instances of the XmlText data type.

M ET H O D N A M E DESC RIP T IO N

AddAfterSelf(Any,...) Adds the specified content immediately after this node.

AddBeforeSelf(Any,...) Adds the specified content immediately before this node.

AsXmlNode() Converts the node to an XmlNode.

GetDocument(var XmlDocument) Gets the XmlDocument for this node.

GetParent(var XmlElement) Gets the parent XmlElement of this node.

Remove() Removes this node from its parent element.

ReplaceWith(Any,...) Replaces this node with the specified content.

SelectNodes(Text, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectNodes(Text, XmlNamespaceManager, var XmlNodeList) Selects a list of nodes matching the XPath expression.

SelectSingleNode(Text, var XmlNode) Selects the first XmlNode that matches the XPath expression.

SelectSingleNode(Text, XmlNamespaceManager, var Selects the first XmlNode that matches the XPath expression.
XmlNode)

Value([Text]) Gets or sets the value of this node.

WriteTo(OutStream) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, OutStream) Serializes and saves the current node to the given variable.

WriteTo(var Text) Serializes and saves the current node to the given variable.

WriteTo(XmlWriteOptions, var Text) Serializes and saves the current node to the given variable.
See Also
Get Started with AL
Developing Extensions
AL Development Environment
2/6/2023 • 2 minutes to read • Edit Online

This section describes all of the objects that are available with the AL Language development environment for
Dynamics 365 Business Central.

TIP
If you are looking for the C/SIDE documentation, visit our Dynamics NAV library.

Defining the AL data model


TO SEE

Learn about how to define new table objects for your Table Object
extension.

Learn about how to modify and extend existing table Table Extension Object
objects.

Presenting the AL data


TO SEE

Learn about how to create new page objects for your Page Object
extension.

Learn about how to modify and extend existing page Page Extension Object
objects.

Learn about how to create page customization objects. Page Customization Object

Learn about how to create profile objects. Profile Object

Learn about how to create report objects. Report Object

Learn about how to create report extension objects. Report Extension Object

Learn about how to create xmlport objects. XmlPort Object

Learn about how to create query objects. Query Object

Learn about how to create control add-in objects. Control Add-In Object

Controlling access to data


TO SEE

Learn about how to create entitlement objects. Entitlement Object

Learn about how to create permissionset objects. Permissionset Object

Learn about how to create permissionset extension objects. Permissionset Extension Object

Writing AL code
TO SEE

Learn about writing codeunits for your extension. Codeunit Object

Get an overview of methods in AL grouped by the data type Data Types and Methods in AL
that they support.

Get an overview of method attributes in AL in alphabetical Method Attributes


order.

Get an overview of option types in AL in alphabetical order. Option Types

Get an overview of properties in AL grouped by the objects Properties Overview


that they support.

Get an overview of triggers in AL grouped by the objects Triggers Overview


that they support.

See Also
Developing Extensions
Get Started with AL
FAQ for Developing in AL
AL Language Extension Configuration
Joker Data Type
2/6/2023 • 2 minutes to read • Edit Online

Joker is an internal data type that is not exposed to AL developers. Joker can replace any other type and
represents a wildcard. In certain cases, Joker plays the role of a generic T which is inferred from the type of the
left-hand side of the invocation expression, in other cases, it is inferred from another parameter.
The following illustrates examples of how Joker is used in AL.

procedure SetRange(Field: Joker, [FromValue: Joker], [ToValue: Joker])

procedure SetFilter(Field: Joker, String: Text, [Value: Joker, ...])

procedure SetAscending(Field: Joker, Ascending: Boolean)

See Also
AL Method Reference
AL Development Environment
Array Methods
2/6/2023 • 2 minutes to read • Edit Online

An array is a data structure that contains many variables, which are accessed through computed indices. An
index is the location of the variable stored in an array. The variables contained in an array are also called the
elements of the array. The array always stores elements of the same data type.
An array has a rank that determines the number of indices that is how long it takes to reach an element. And if
there are repeating elements, their rank will be same as their first occurrence in the array. The rank of an array is
also referred to as the dimension of the array. An array with a rank of one is called a single-dimensional array.
An array with a rank greater than one is called a multi-dimensional array. Specific sized multi-dimensional
arrays are often referred to as two-dimensional arrays, three-dimensional arrays, and so on. Each dimension of
an array has an associated length, which is an integral number greater than or equal to zero. The maximum
number of dimensions is 10 and the total number of elements in all dimensions is 1,000,000.
The length of a dimension determines the valid range of indices for that dimension. For a dimension of length N,
indices can range from 1 to N inclusive. The total number of elements in an array is the product of the lengths
of each dimension in the array. If one or more of the dimensions of an array have a length of zero, the array is
considered to be empty.

Syntax
The syntax for declaring an array of a specific type is the following:

Array [Dimension] of Type;

The Dimension is a comma-delimited list of integer literals greater than 0, where each integer defines the
number of elements in that dimension.
The Type is the element type of the array.

Code example
The following code sample shows the declaration of an array with a simple element type.

ArrayOfInteger: Array [10] of Integer;

The following code sample shows the declaration of an array with an element type of a fixed length.

ArrayOfCode: Array [10] of Code[20];


ArrayOfText: Array [10] of Text[20];

The following code sample shows the declaration of an array with a complex element type.

ArrayOfCodeunits: Array [10] of Codeunit 10;


ArrayOfQueryes: Array [10] of Query "My Query";
ArrayOfTemporaryRecords: Array [10] of Record 10 Temporary;
ArrayOfDotNetVariables: Array [10] of DotNet String;
Methods
The following AL methods for arrays are available:
ArrayLen Method
CompressArray Method
CopyArray Method

Array of temporary records


The following code sample shows the declaration of an array of temporary Item records:

ItemRecArrayTemp: Array[2] of Record Item temporary;

In this case, each element of the array will contain a temporary Item record referencing the same temporary
table, meaning that an insert into ItemRecArrayTemp[0] is also reflected in ItemRecArrayTemp[1] .
This is the same behavior as using Copy(RecordRef [, Boolean]) with the ShareTable parameter set to true .

See Also
AL Method Reference
Dictionary Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents an unordered collection of keys and values. The Dictionary data type is optimized for fast lookup of
values.
The following methods are available on instances of the Dictionary data type.

M ET H O D N A M E DESC RIP T IO N

Add(TKey, TValue) Adds the specified key and value to the dictionary.

ContainsKey(TKey) Determines whether the Dictionary contains the specified


key.

Count() Gets the number of key/value pairs contained in the


Dictionary.

Get(TKey, var TValue) Gets the value associated with the specified key.

Get(TKey) Gets the value associated with the specified key.

Keys() Gets a collection containing the keys in the Dictionary.

Remove(TKey) Removes the value with the specified key from the
Dictionary.

Set(TKey, TValue) Sets the value associated with the specified key.

Set(TKey, TValue, var TValue) Sets the value associated with the specified key.

Values() Gets a collection containing the values in the Dictionary.

Remarks
Each addition to the dictionary consists of a value, and its associated key. Every key in a Dictionary must be
unique. A key cannot be null, but a value can be, only when the value type is a reference type.
The Dictionary data type does not support holding instantiated records. For this purpose, use temporary tables.

WARNING
Previously in C/AL, one would have typically used an in-memory temporary table to create a key-value data structure, as
shown in the code below. In AL you use the Dictionary Data Type instead.

IF KeyCacheRec.Get(‘Some Value’) THEN


Complete data stack execution;
Example
In the following example, the variable counter represents the Dictionary data type to store a value representing
the number of occurrences for each character in the customerName . Using the Get method, you get the number
of occurrences for the character at position i . If i returns false , it means there is no value associated with
that character, so you add the value 1. If i returns true , it means the value already exists, so you add c + 1 to
the value. The Add method adds the {key:value} pair to the Dictionary.

procedure CountCharactersInCustomerName(customerName: Text; var counter: Dictionary of [Char, Integer]);


var
i : Integer;
c : Integer;
begin

for i := 1 to StrLen(customerName) do
begin
if counter.Get(customerName[i], c) then
counter.Set(customerName[i], c + 1)
else
counter.Add(customerName[i], 1);
end;
end;

See Also
Get Started with AL
Developing Extensions
List Data Type
List Data Type
2/6/2023 • 3 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Represents a strongly typed list of ordered objects that can be accessed by index. Contrary to the Array data
type, a List is unbounded, such that its dimension does not need to be specified upon declaration.
The following methods are available on instances of the List data type.

M ET H O D N A M E DESC RIP T IO N

Add(T) Adds a value to the end of the List.

AddRange(T [, T,...]) Adds the elements of the specified collection to the end of
the list.

AddRange(List of [T]) Adds the elements of the specified collection to the end of
the list.

Contains(T) Determines whether an element is in the List.

Count() Gets the number of elements contained in the List.

Get(Integer, var T) Gets the element at the specified index.

Get(Integer) Gets the element at the specified index. This method will
raise an error if the index is outside the valid range.

GetRange(Integer, Integer) Get a shallow copy of a range of elements in the source.

GetRange(Integer, Integer, var List of [T]) Get a shallow copy of a range of elements in the source.

IndexOf(T) Searches for the specified value and returns the one-based
index of the first occurrence within the entire List.

Insert(Integer, T) Inserts an element into the List at the specified index.

LastIndexOf(T) Searches for the specified value and returns the one-based
index of the last occurrence within the entire List.

Remove(T) Removes the first occurrence of a specified value from the


List.

RemoveAt(Integer) Removes the element at the specified index of the List.

RemoveRange(Integer, Integer) Removes a range of elements from the List.

Reverse() Reverses the order of the elements in the entire List.


M ET H O D N A M E DESC RIP T IO N

Set(Integer, T) Sets the element at the specified index.

Set(Integer, T, var T) Sets the element at the specified index.

Remarks
The List can only be used with simple types i.e. you can have a List of [Integer] but cannot have a List of [Blob].
Similarly, the List data type does not support holding instantiated records. For this purpose, use temporary
tables.
Lists are 1-based indexed, that is, the indexing of a List begins with 1.
A List is a reference type, so assigning an instance of a list to another variable or passing as a method parameter
by value (for example without var), creates a second variable that reads/writes the same list. It does not create a
new list.
To create a new list that contains the same values as the original list, you can do the following to perform a
shallow copy:

trigger OnRun()
var
l1: List of [Integer];
l2: List of [Integer];
begin
l2 := l1.GetRange(1, l1.Count);
end;

A shallow copy does not copy the elements within the list, only the list itself, so if the elements within the list are
reference types as well, for example a list of lists, they will still be the same lists as in the original list.
To perform a deep copy, meaning to copy reference types within reference types, you will need to apply the
same approach to the elements of the list:

trigger OnRun()
var
innerlist: List of [Integer];
l1: List of [List of [Integer]];
l2: List of [List of [Integer]];
begin
foreach innerlist in l1 do begin
l2.Add(innerlist.GetRange(1, innerlist.Count));
end;
end;

WARNING
Previously in C/AL, one would have typically used an in-memory temporary table to create an unbounded "array" data
structure, as shown in the code below. In AL you use the List Data Type instead.

listRec.Value := ‘Some Value’;


listRec.Insert();
Example
In the following example, the variable CustomerNames is a list of Text values which represent customer names.
The procedure WorkWithListOfCustomers displays how one would work with the List data type. The Add method
is used to add the string 'John' to the CustomerNames list. The Contains method is used to check whether the
list contains the specified value, in this case, the string 'John' . We continue by using the Message procedure to
display a relevant message.

procedure WorkWithListOfCustomers();
var
customerNames : List of [Text];
begin
// Adding an element to the list
customerNames.Add('John');

// Checking if the list contains an element


if customerNames.Contains('John') then
Message('John is in the list')
else
Message('John is not in the list')
end;

See Also
Get Started with AL
Developing Extensions
Dictionary Data Type
Extensible Enums
2/6/2023 • 4 minutes to read • Edit Online

An enumeration type, also known as an enum in programming, is a keyword used to declare a type that consists
of a set of named constants. The list of named constants is called the enumeration list. Enums can be used as
table fields, local and global variables, and parameters.
To declare an enum in AL you must specify an ID and a name. The enumeration list consists of values and each
of the values are declared with an ID and a value. The value ID is the ordinal value on the enumeration list and
must be unique. When the enum values are displayed in the UI they're sorted by the order of declaration. In
addition, if extension B extends extension A , the enum values declared in extension A are displayed before the
enum values declared in extension B .
The following example shows the declaration of an enum, which can be extended, and has the four values;
None , Bronze , Silver , and Gold .

enum 50121 Loyalty


{
Extensible = true;

value(0; None) { }
value(1; Bronze) { }
value(2; Silver) { }
value(3; Gold)
{
Caption = 'Gold Customer';
}
}

NOTE
While enums and enumextension objects have object IDs, these are not enforced by the license. In previous versions they
reused the range for tables, and were checked against the license at deployment time, but this is no longer the case.
Uniqueness validation is now enforced during installation, which will fail if an enum object ID clashes with an already
installed enum. Thus, as always, it is important that you use object IDs in your assigned range. This is enforced for
AppSource apps, but not for per-tenant extensions, or on-premise. The enum does not have to use the same ID as the
table it is put on.

IMPORTANT
Only enums with the Extensible Property set to true can be extended.

IMPORTANT
When creating captions for enums, it's important that the caption doesn't contain a comma. Having a comma in the
caption, such as Caption = 'Diamond Level, with bonus' , can display over multiple lines in the UI. This behavior also
causes that the actual value selected by the user in the UI, doesn't correspond to the value, which is saved in the
database.
An AppSourceCop warning will be triggered if .xlf files contain commas in enum captions. For more information, see
AppSourceCop Warning AS0087.
Enumextension object
Enums can be extended in order to add more values to the enumeration list in which case the Extensible
property must be set to true . The syntax for an enum extension, which extends the Loyalty enum with the
value Diamond , is shown below.

enumextension 50130 LoyaltyWithDiamonds extends Loyalty


{
value(50130; Diamond)
{
Caption = 'Diamond Level';
}
}

Usage
When referencing a defined enum from code, you use the syntax as illustrated below.
enum Loyalty

If you want to define an enum as a table field type, use the syntax illustrated below:

field(50100; Loyal; enum Loyalty) {}

Or, as a variable:

var
LoyaltyLevel: enum Loyalty;

In code, you address a specific enum value like in the following example:

codeunit 50140 EnumUsage


{
procedure Foo(p: enum Loyalty)
var
LoyaltyLevel: enum Loyalty;
begin
if p = p::Gold then begin
LoyaltyLevel := p;
end;
end;
}

Example
The following example illustrates how to define an enum extension of TypeEnum , using it in a table extension
TableWithRelationExt and displaying it as a control on a new page.
enumextension 50133 TypeEnumExt extends TypeEnum
{
value(10; Resource) { }
}

tableextension 50135 TableWithRelationExt extends TableWithRelation


{
fields
{
modify(Relation)
{
TableRelation = if (Type = const (Resource)) Resource;
}
}
}

page 50133 PageOnRelationTable


{
SourceTable = TableWithRelation;
SourceTableView = where (Type = const (Resource));
PageType = List;

layout
{
area(Content)
{
repeater(MyRep)
{
field(Id; Id)
{
ApplicationArea = All;
}
field(Type; Type)
{
ApplicationArea = All;
}
field(Relation; Relation)
{
ApplicationArea = All;
}
}
}
}
}

TIP
For another example of how to extend the usage of the TableRelation property in connection with enums, see
TableRelation Property.

Business Central on-premises


If you want to extend an existing Dynamics 365 on-premises enum, it's possible to mark a table field in C/SIDE
as extensible. To enable running C/SIDE and AL side-by-side, see Running C/SIDE and AL Side-by-Side.
Table field options in C/SIDE have three properties to enable enum support:

P RO P ERT Y N A M E DATA T Y P E

Extensible Boolean, default value is No .


P RO P ERT Y N A M E DATA T Y P E

EnumTypeId Integer

EnumTypeName Text

Some table fields share options that are semantically identical. In those cases, the EnumTypeId and
EnumTypeName must be the same across all the fields. There's no design or runtime check for collision of IDs,
but loading generated symbols, see Running C/SIDE and AL Side-by-Side, into the compiler will show collision
errors.
Conversions
Conversion to and from enum is more strict than for Options in C/SIDE.
An enum can be assigned/compared to an enum of the same type.
To be backwards compatible, we support conversion to/from any Option for now.

For information about assignment compatibility, see AssignmentCompatibility Property.

See Also
AL Data Types
TableRelation Property
Extensible Property
Enum Data Type
AssignmentCompatibility Property
Option Data Type
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Denotes an option value. In the code snippet below, you can see how the Option data type is declared.

Syntax example
procedure HelloWithOptions(OptionParameter : Option Alpha, "Bra-vo")
var
OptionVariable : Option C, "or D";
begin
Message('%1',OptionParameter::Alpha);
Message('%1',OptionVariable::C);
end;

NOTE
It is not possible to reference the members of the OptionParameter from outside the body of the procedure.

Remarks
In the OptionString Property of the field or variable, you can enter the option values as a comma-separated list.
The Option type is a zero-based enumerator type, which means that the option values are assigned to sequential
numbers, starting with 0. You can convert option data types to integers.

Example 1
The following code sample shows how to define an option field in a table.

field(0; PreferredContactMethodCode; Option)


{
Caption = 'Preferred Method of Contact';
// The OptionMembers property must be defined on an option field. It specifies which values can the
field take.
OptionMembers = Any,Email,Phone,Fax,Mail;
}

Example 2
This example shows how you can use the value of an option field as a constant in your AL code.

PurchHeaderRec."Document Type" := PurchHeaderRec."Document Type"::Invoice;

See Also
Get Started with AL
Developing Extensions
Interfaces in AL
2/6/2023 • 2 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1

An interface in AL is similar to an interface in any other programming language; it is a syntactical contract that
can be implemented by a non-abstract method. The interface is used to define which capabilities must be
available for an object, while allowing actual implementations to differ, as long as they comply with the defined
interface.
This allows for writing code that reduces the dependency on implementation details, makes it easier to reuse
code, and supports a polymorphic way of calling object methods, which again can be used for substituting
business logic.
The interface declares an interface name along with its methods, and codeunits that implement the interface
methods, must use the implements keyword along with the interface name(s). The interface itself does not
contain any code, only signatures, and cannot itself be called from code, but must be implemented by other
objects.
The AL compiler checks to ensure that implementations adhere to assigned interfaces.
You can declare variables as a given interface to allow passing objects that implement the interface, and then call
interface implementations on the passed object in a polymorphic manner.

Snippet support
Typing the shortcut tinterface will create the basic layout for an interface object when using the AL Language
extension in Visual Studio Code.

Interface example
The following example defines an interface IAddressProvider , which has one method getAddress with a certain
signature. The codeunits CompanyAddressProvider and PrivateAddressProvider both implement the
IAddressProvider interface, and each define a different implementation of the getAddress method; in this case
a simple variation of address value.
The MyAddressPage is a simple page with an action that captures the choice of address and calls, based on that
choice, an implementation of the IAddressProvider interface.

interface "IAddressProvider"
{
procedure GetAddress(): Text
}

codeunit 50200 CompanyAddressProvider implements IAddressProvider


{

procedure GetAddress(): Text;


var
ExampleAddressLbl: Label 'Company address \ Denmark 2800';

begin
exit(ExampleAddressLbl);
end;
}

codeunit 50201 PrivateAddressProvider implements IAddressProvider


{

procedure GetAddress(): Text;


var
ExampleAddressLbl: Label 'My Home address \ Denmark 2800';

begin
exit(ExampleAddressLbl);
end;
}

enum 50200 SendTo implements IAddressProvider


{
Extensible = true;

value(0; Company)
{
Implementation = IAddressProvider = CompanyAddressProvider;
}

value(1; Private)
{
Implementation = IAddressProvider = PrivateAddressProvider;
}
}

page 50200 MyAddressPage


{
PageType = Card;
ApplicationArea = All;
UsageCategory = Administration;

layout
{
area(Content)
{
group(MyGroup)
{
}
}
}

actions
{
area(Processing)
{
action(GetAddress)
{
ApplicationArea = All;

trigger OnAction()
var
AddressProvider: Interface IAddressProvider;
begin
AddressproviderFactory(AddressProvider);
Message(AddressProvider.GetAddress());
end;
}

action(SendToHome)
{
ApplicationArea = All;

trigger OnAction()
begin
sendTo := sendTo::Private;
end;
}

action(SendToWork)
{
ApplicationArea = All;

trigger OnAction()
begin
sendTo := sendTo::Company;
end;
}
}
}

local procedure AddressproviderFactory(var iAddressProvider: Interface IAddressProvider)


begin
iAddressProvider := sendTo;
end;

var
sendTo: enum SendTo;
}

See Also
Codeunit Object
Extensible Enums
AL methods
2/6/2023 • 5 minutes to read • Edit Online

Like other languages, AL methods are a fundamental programming element. A method, also known as a
procedure, is a named group of statements that perform an operation or task. Depending on the scope,
methods can be run, or called, from the same object in which they are declared or from other parts of the
application.
There are two types of methods: system methods (built-in) and user-defined (custom) methods.
Built-in methods are part of the platform. Built-in methods can be used for different purposes, such as
string handling, text formatting, database handling, and so on. For information about the available built-in
methods, see AL method Reference and Essential AL methods. For information about method scope, see
Scope Attribute.
Custom methods are specialized methods for your application to bind the objects, such as tables, pages,
and code units, together to form a unified whole. You can create special methods for use anywhere in the
database.

TIP
If you already know the name of, for example, a data type, method, property, or trigger, use the Filter by title field in the
upper left corner, above the table of contents to find the topic faster. Otherwise, you can scan the table of contents to find
it.

Declaring methods
The method declaration defines the method and has the following syntax:

[Attributes(arguments list)]
local procedure <method_name>(parameter list) <return_value_name> : <data_type>[<length>]

Snippet support
Typing the shortcut tprocedure will create the basic structure for a method when using the AL Language
extension in Visual Studio Code.
Attributes (optional)
An attribute is a modifier on a method declaration that specifies information that controls the method's use and
behavior. Adding an attribute on a method declaration is also known as decorating a method. For example,
decorating a method with the Integration attribute sets the method to be an event publisher. An attribute can
have one or more arguments that set properties for the method instance.
Attributes are placed before the method. For information about the available attributes, see Method Attributes.
Local and global scope
A method can be a local method or global method. A local method can only be accessed or called from inside
the object in which it is declared. A global method can be called from inside the object in which it is declared and
from other objects.
To declare a local method, start the declaration with local :
local procedure Mymethod();

To declare a global method, omit local :

procedure Mymethod();

Parameters (optional)
A parameter is one or more variables or expressions that are sent to the method through the method call. The
parameter provides information to the method, and the method can modify that information. In the method
declaration, you place the parameters in parentheses () . If there is more than one parameter, the parameters
are separated by semicolons. A parameter is defined by a data type. Some data types, such as Record , require
an additional subtype.
For example, the following method declaration includes two parameters: MyCustomer and MyDimension :

procedure MyMethod(MyCustomer : Record Customer; var MyDimension : ARRAY [2] OF Boolean)

This example also illustrates how parameters can be passed by value or passed by reference. The MyCustomer
parameter is passed by value, and the MyDimension parameter is passed by reference in the example above. For
more information, see the section Parameters below.
Return values (optional)
A method can return data that can be then coded against. A return value is defined by a name (optional), data
type, and optional length depending on the data type.
For example, if the return value is a Text DataType, the text might have a length of 50.

procedure MyMethod() ReturnValue: Text[50]


var result : Text[50];
begin
// do something important where result is calculated
ReturnValue := result;
end;

Calling methods
You can run, or call, a built-in or a custom method by using its name in a method call statement. When a method
is called the current application sequence is suspended and the code on the method is run. When the method
code is completed, the application code sequence returns to where the method was called from. How the
method is called determines what happens when it returns.
A method can be used as part of an expression. For example, the following code uses a method named
CalculatePrice as an expression:

TotalCost := Quantity * CalculatePrice;

In this case, the CalculatePrice method must return a value that is used in evaluating the expression. This
return value is then multiplied by the Quantity variable and that result is assigned to the TotalCost variable.
A method can also be run by using a method call statement. This statement only calls the method and does not
return any value. The following is an example of calling a method named MyRunMethod :
if Quantity > 5 then
MyRunMethod;

The MyRunMethod returns no data back to the calling code.


Parameters
In a method call, the parameters are separated by commas, and the optional parameters may be omitted
starting from the right. For example, this means that if a method has three optional parameters, then you cannot
omit the second parameter without omitting the third parameter.
When passing parameters there are two options; passing by value, which is the default behavior, or passing by
reference, in which case you must specify the var keyword.
If a parameter is passed by value, then a copy of the variable is passed to the method. Any changes that
the method makes to the value of the variable are local changes that affect only the copy, not the variable
itself.
If a parameter is passed by reference, then a reference to the variable is passed to the method. The
method can change the value of the variable itself.

Example 1
The following shows the syntax for a method. The first example shows a method with two mandatory
parameters.

method(Parameter1, Parameter2)

Some built-in methods have optional parameters, the syntax is shown below. The optional parameters may be
omitted starting from the right.

method([Optional1] [, Optional2] [, Optional3])

The method that uses the syntax above can be called by using the following code.

method(Optional1, Optional2)

Example 2
ABS is an example of an AL method that has a fixed number of parameters (1).

Value := -1033; //A negative integer value


PositiveValue := ABS(Value); //Calculate the positive value 1033

Example 3
The method DMY2DATE is an example of a method that can be called by using a variable number of parameters.

NewDate := DMY2DATE(5, 11, 1992); //Returns the date November 5, 1992

Depending on the use of the DMY2DATE method, one, two, or three parameters can be passed to the method
because the second and third parameters are optional. When the second and third parameters are not used,
values from the system date are used as default values.

Example 4
You can assign the return value of a method to a variable.

ReturnVal := MyMethod(Param1);

Example 5
In this example, MyMethod returns a Boolean value. You can use the return value in a conditional statement.

if (MyMethod(Param1)) then
<Statement1>
else
<Statement2>

See Also
Development Overview
AL Methods
AL Simple Statements
AL Control Statements
Progress Windows, Message, Error, and Confirm
Methods
2/6/2023 • 4 minutes to read • Edit Online

You can use several specialized methods to display messages and gather input. We recommend that you use
pages to ensure that your application has a consistent user interface. However, there are situations where you
may want to use the dialog methods instead of pages. The most important uses of the dialog methods are as
follows:
To display a window that indicates the progress of some processing that may take a long time.
To stop the running program to display an error message.
To let the user confirm a choice before the program continues running.
You can also use the StrMenu method to create pages that present options to the user. It's much faster to use this
method than to design a page, which only presents a limited set of options to the user. For more information
about the StrMenu method, see StrMenu Method.

Best practices for user messages


We recommend the following guidelines for writing messages for end users:
Write messages correctly according to the grammatical rules for your language.
Don't use backslashes to indicate line breaks in a message. Line formatting is completed automatically.
The only exception is in the Open Method). You must use backslashes for the message to be aligned
correctly.
Use the FieldCaption Method) and TableCaption Method) whenever possible to return names of fields
and tables as strings. It's so that the user can always recognize a term that indicates a field or table name.
The only exception to this is in Open Method) where you can use the field name directly. Otherwise, it can
be difficult to align correctly. If you refer to a field name without using the FieldCaption method, then type
the field name without any single or double quotation marks.
Try to write all messages on only one line. If you want to use more than one line, then start a new line
after a period instead of in the middle of a sentence.
Don't enter the text directly in the AL code. Instead, enter it as a label so that the message can be
translated.

Creating a window to indicate progress


If you have an application whose processing can take a long time to complete, then you should consider
displaying a window that informs the user of the progress that is being made. It's always a good idea to inform
the user that processes are still running.
A Cancel button is automatically added to every dialog window and gives user the opportunity to stop the
processing.
In some applications, you may want to create a window in which each field is updated when the program is
running. For example, the fields in the window, display the count of the postings made. In another application,
you may want to display information about the record that is currently being processed. For example, the field in
the window, displays the number of the account that is currently being processed.
To create this kind of progress window, you use the Dialog data type.

Message method
The Message Method) displays a message in a window that remains open until the user chooses the OK button.
The Message method has the following syntax.

message(String [, Value1, ...]);

The Message method runs asynchronously, which means that the message isn't run until the method from
which it was called ends or another method requests user input. The method is useful for notifying the user that
some processing has been successfully completed.
For an example of the Message method, see codeunit 83 in the CRONUS International Ltd. demonstration
database. The code in the OnRun trigger converts a quote into a sales order and then displays a message. The
message is generated by the following code.

var
Text001 : Label 'Quote %1 has been changed to order %2';

message(Text001,"No.",SalesHeader2."No.");

NOTE
Unlike the progress window, the Message method doesn't require that you first declare a variable of the type Dialog. The
Message method creates a window of its own.

Error method
The Error Method) is similar to the Message method except that when the user has acknowledged the message
from an Error method, execution ends. The Error method is also similar to the FieldError method. For more
information, see CalcFields, CalcSums, FieldError, FieldName, Init, TestField, and Validate Methods.
The Error method has the following syntax.

Error(String [, Value1, ...]);

Confirm method
The Confirm Method) is used just like the Message method to display a message. However, unlike the Message
method, the Confirm method has a required return value.
The Confirm method has the following syntax.

Ok := Dialog.Confirm(String [, Default] [, Value1] ,...);

The following example shows how to use the Confirm method.


if confirm('Do you want to post the journal lines and print report %1?', False, ReportID) then
message('Posting')
else begin
message('No Posting');
exit;
end;

The false parameter in the confirm statement means that No is the default.

See Also
Dialog Data Type
Method Attributes
2/6/2023 • 2 minutes to read • Edit Online

An attribute is a modifier on a method declaration that specifies information that controls the method's use and
behavior. Adding an attribute on a method declaration is also known as decorating a method. For example,
decorating a method with the Integration attribute sets the method to be an event publisher. An attribute can
have one or more arguments that set properties for the method instance.
In AL, attributes are placed before the method, and they have the following syntax:

[Attribute_Name(ArgumentName : data_type, ArgumentName : data_type)]

For example, the Integration attribute has two arguments, and the syntax is:

[Integration(IncludeSender : Boolean, GlobalVarAccess : Boolean)]

TIP
If you already know the name of, for example, a data type, method, property, or trigger, use the Filter by title field in the
upper left corner, above the table of contents to find the topic faster. Otherwise, you can scan the table of contents to find
it.

See Also
AL Method Reference
AL Complex Types
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

With the latest version of Business Central, it's possible to return most types from procedures - both user-
defined types and most built-in types.
The method in the example below, will take a name, and return the first customer record that matches the name.
The signature specifies the return type at the end of the procedure declaration, and the procedure exits by
returning the found customer record.

///<summary>
/// Getthefirstcustomerwithnamestartingwith<paramref name="Name"/>
///</summary>
///<param name="Name">Namefilter</param>
///<returns>Firstcustomer</returns>

procedure GetCustomerByName(Name: Text): record Customer;


var
Customer: record Customer;
begin
Customer.SetFilter(Name, '@' + Name + '*');
Customer.FindFirst();
exit(Customer);
end;

It's also possible to use a named return value. Internally, the exit-statement as seen in the example above causes
an assignment to an allocated return value. The assignment will have a small performance cost based on the
type. Since the record type is treated as a value-type, it's better.

procedureGetCustomerByName(Name:Text) Customer:recordCustomer;
begin
Customer.SetFilter(Name,'@'+Name+'*');
Customer.FindFirst();
end;

The method GetCustomerByName() returns a Customer record. It can be used as you would expect in the
following example.

//Getthe firstcustomerwithnamestartingwith'spo'

Customer:=GetCustomerByName('spo');

The returned value doesn't have to be used in an assignment statement. It can be used as part of an expression
like in the following example.

//Use the returned value as an expression.

DoSomethingWithSales(GetCustomerByName('spo').GetSalesLCY());

It doesn't only work for user-defined types like records, codeunits, etc., but also for built-in types. For example,
when using the HttpClient Data Type, it's possible to write code as illustrated below.

///<summary>
///Returnsabing-readyHttpClient
///</summary>
///<returns>BingHttpClient</returns>
procedure GetBingClient() Result: HttpClient;
begin
Result.SetBaseAddress('https://www.bing.com');
end;

///<summary>
///Gettheresponsefromarequesttobing.
///</summary>
///<returns>Theresponsemessage</returns>

procedure GetBingResponse() Response: HttpResponseMessage


begin
GetBingClient().Get('', Response)
end;

///<summary>
///Gettheresponsefromwww.bing.comasanhtml-string.
///</summary>
///<returns>stringwithhtml</returns>
procedure GetBingHtml() Result: Text;
begin
GetBingResponse().Content().ReadAs(Result);
end;

See Also
Programming in AL
AL Simple Statements
Directives in AL
AL Essential Methods
HttpClient Data Type
Procedure overload
2/6/2023 • 2 minutes to read • Edit Online

Procedure overload enables developers to create multiple procedures with the same name, but with different
signatures, on the same application object. Conceptually, overloaded procedures are used to execute the same
task on a different set of arguments. When an overloaded procedure is called, a specific implementation of that
procedure, appropriate to the context of the call, will be run.

Reasons for using procedure overload


Overloaded procedures give programmers the flexibility to call a procedure with similar semantics for different
types of data. At the same time, overloaded procedures remove the need for abusing the Variant data type for
the purpose of processing different types of data in a similar manner and allows the developer to write strongly-
typed code and rely on the compiler for validation.
Remarks
Overload resolution is performed by using procedure signatures to find the best match. The signature of a
procedure is represented by its name and the type, order, and number of parameters. The return type of a
procedure is not part of the procedure’s signature.

Example
The following example shows how a ToString method can be implemented with and without using procedure
overloads.
In the first code snippet, a ToString procedure is implemented. This takes a Variant value and inspects the type
of the value to delegate to different implementations. If the caller passes a value of a different type than Integer,
Date, and Text, an empty string will be returned. This can lead to bugs that will only show up at runtime.
codeunit 10 Stringifier
{
local procedure TextToString(value : Text) : Text;
begin
Exit(value);
end;

local procedure DateToString(value : Date) : Text;


begin
Exit(Format(value));
end;

local procedure IntegerToString(value : Integer) : Text;


begin
Exit(Format(value));
end;

procedure ToString(value: Variant) : Text;


begin
if value.IsInteger then
Exit(IntegerToString(value))
else if value.IsDate then
Exit(DateToString(value))
else if value.IsText then
Exit(TextToString(value))
else
Exit('');
end;
}

In the second code snippet, we overload the ToString procedure for Text, Date and Integer. At this point, it is not
possible for a caller to call a ToString method with a different type other than Integer, Date, or Text. This will catch
the bug above at compile time.

codeunit 10 StringifierWithOverloads
{
procedure ToString(value : Text) : Text;
begin
Exit(value);
end;

procedure ToString(value : Date) : Text;


begin
Exit(Format(value));
end;

procedure ToString(value : Integer) : Text;


begin
Exit(Format(value));
end;
}

See Also
AL Method Reference
AL Development Environment
Create Handler Methods
2/6/2023 • 2 minutes to read • Edit Online

You can create test codeunits, test methods, and test pages to test your application. We recommend that you
create tests that can be automated. To create automated tests, you must write code to handle all UI interactions
so that the tests don't require user interaction when they're running. To do this, you create special handler
methods.
You can use the following handler methods:

M ET H O D T Y P E P URP O SE SIGN AT URE

MessageHandler Handles Message statements. <Function name>(<Message>:


Text[1024])

ConfirmHandler Handles Confirm statements. <Function name>(<Question>:


Text[1024]; var <Reply>: Boolean)

StrMenuHandler Handles StrMenu statements. <Function name>(<Options:


Text[1024]; var <Choice>: Integer;
<Instruction>: Text[1024])

PageHandler Handles specific pages that aren't run <Function name>(var <Page>: Page
modally. <page id>)

<Function name>(var <Page>:


TestPage <testpage id>)

ModalPageHandler Handles specific pages that are run <Function name>(var <Page>: Page
modally. <page id>; var <Response>: Action)

<Function name>(var <Page>: Page


<testpage id>)

ReportHandler Handles specific reports. If you create a <Function name>(var <Report>:


Repor tHandler method, then that Report <report id>)
method replaces all code for running
the report, including the request page,
and a RequestPageHandler isn't
called. Only create a
RequestPageHandler if you aren't
using a ReportHandler.

FilterPageHandler Handles a specific filter page. The <Function name>(var <Record1>:


FilterPageHandler tests the UI that is RecordRef)[, var <Record2>: RecordRef]
generated by a FilterPageBuilder Data [, ...]): Boolean
Type.

RequestPageHandler Handles the request page of a specific <Function name>(var <RequestPage>:


report. TestRequestPage)

HyperlinkHandler Handles specific hyperlinks. <Function name>(<Hyperlink>:


Text[1024])
M ET H O D T Y P E P URP O SE SIGN AT URE

SendNotificationHandler Handles Send statements. <Function name>(<TheNotification>:


Notification): Boolean

RecallNotificationHandler Handles Recall statements. <Function name>(<TheNotification>:


Notification): Boolean

SessionSettingsHandler Handles RequestSessionUpdate <Function name>(var


statements. <SessionSettings>: SessionSettings):
Boolean

How to create a handler method


To create a handler method, you set one of the handler attributes on a method. You must use the method
signature specified for the handler attribute that you're using, as illustrated in this code example.

[MessageHandler]
procedure MessageHandler(Message: Text[1024])
begin
Assert.IsTrue(StrPos(Message, MSG_HAS_BEEN_CREATED) > 0, Message);
end;

The parameters of the methods that are being handled are passed as parameters to the handler methods. For
example, when Message is called in a test method, the parameter of the Message method is passed as the
parameter of the MessageHandler method. For page and report handlers, the page, report, or request page is
passed as the parameter of the PageHandler , ModalPageHandler , Repor tHandler , or
RequestPageHandler .
You can call handler methods from methods that have the Test Attribute and then specify the handler methods
that it will use in the HandlerFunctions Attribute. The code inside the test method should simulate that the UI
was actually raised and some values entered or some actions were taken. You can specify more than one
handler method by separating the handler method names with a comma.

NOTE
Every handler method that you enter in the HandlerFunctions Attribute of a test method must be called at least one time
in the test method. If you run a test method that has a handler method listed that isn't called, then the test fails.

The following example shows a test method that uses the HandlerFunctions Attribute to call the
MessageHandler method.

[Test]
[HandlerFunctions('MessageHandler')]
procedure ApproveRequestForPurchCreditMemo()
var
PurchHeader: Record "Purchase Header";
begin
ApproveRequestForPurchDocument(PurchHeader."Document Type"::"Credit Memo");
end;

See Also
Testing the Application
AL Methods
Properties Overview
2/6/2023 • 2 minutes to read • Edit Online

This section describes the properties that are available to developers in Dynamics 365 Business Central for
controlling the behavior of objects, like tables, pages, and reports.

TIP
If you already know the name of, for example, a data type, method, property, or trigger, use the Filter by title field in the
upper left corner, above the table of contents to find the topic faster. Otherwise, you can scan the table of contents to find
it.

There are different properties for various the AL object types. Some properties can be set on the object-level,
and others pertain to specific controls of the object. Properties are added at the beginning of the code for the
object or control, after the its definition, by using the syntax: Property_name = value; . For example:

page 50100 MyPage


{
// Page object properties
PageType = Card;
ApplicationArea = All;
UsageCategory = Administration;
SourceTable = Customer;

layout
{
area(Content)
{
group(GroupName)
{
field(Name; Name)
{
// Field properties
ApplicationArea = All;
}
}
}
}

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on selecting a property and help on its syntax.

See Also
Methods
Triggers
Table Object
2/6/2023 • 2 minutes to read • Edit Online

Tables are the core objects used to store data in Dynamics 365 Business Central. No matter how data is
registered in the product - from a web service to a finger swipe on the phone app, the results of that transaction
will be recorded in a table.
The structure of a table has four sections:
The first block contains metadata for the overall table, such as the table type.
The fields section describes the data elements that make up the table, such as their name and the type of data
they can store.
The keys section contains the definitions of the keys that the table needs to support.
The final section details the triggers and code that can run on the table.

IMPORTANT
Only tables with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

IMPORTANT
System and virtual tables can't be extended. System tables are created in the ID range of 2.000.000.000 and above. For
more information about object ranges, see Object Ranges.

Snippet support
Typing the shortcut ttable will create the basic layout for a table object when using the AL Language extension
in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Table example
This table stores address information and it has four fields; Address , Locality , Town/City , and County .
table 50104 Address
{
Caption = 'Sample table';
DataPerCompany = true;

fields
{
field(1; Address; Text[50])
{
Description = 'Address retrieved by Service';
}
field(2; Locality; Text[30])
{
Description = 'Locality retrieved by Service';
}
field(3; "Town/City"; Text[30])
{
Description = 'Town/City retrieved by Service';
}
field(4; County; Text[30])
{
Description = 'County retrieved by Service';

trigger OnValidate();
begin
ValidateCounty(County);
end;

}
}
keys
{
key(PrimaryKey; Address)
{
Clustered = TRUE;
}
}

var
Msg: Label 'Hello from my method';

trigger OnInsert();
begin

end;

procedure MyMethod();
begin
Message(Msg);
end;
}

System fields
The Dynamics 365 Business Central platform will automatically add several system fields to tables. For more
information, see System Fields.

See Also
AL Development Environment
Table Overview
Table Extension Object
SqlTimestamp Property
Table Keys
Table, Table Fields, and Table Extension Properties
Table Extension Object
2/6/2023 • 2 minutes to read • Edit Online

The table extension object allows you to add additional fields or to change some properties on a table provided
by the Dynamics 365 Business Central service. In this way, you can add data to the same table and treat it as a
single table. For example, you may want to create a table extension for a retail winter sports store. In your
solution you want to have ShoeSize as an additional field on the customer table. Adding this as an extension
allows you to write code for the customer record and also include values for the ShoeSize .
Along with defining other fields, the table extension is where you write trigger code for your additional fields.
When developing a solution for Dynamics 365 Business Central , you will follow the code layout for a table
extension as shown in the example below.

IMPORTANT
Only tables with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

IMPORTANT
System and virtual tables cannot be extended. System tables are created in the ID range of 2.000.000.000 and above. For
more information about object ranges, see Object Ranges.

IMPORTANT
Extending tables from Dynamics 365 for Sales is currently not supported.

Using a table extension to add a key to the base table


Just like in the table object, you can define keys for fields added in the table extension. But you can also add keys
for fields that only exist on the table you extend, in case you want to extend the keys provided in the base table
definition. See Table Keys for examples on how to define keys in a table extension.

Snippet support
Typing the shortcut ttableext will create the basic layout for a table extension object when using the AL
Language extension in Visual Studio Code.

Properties
Using a table extension allows you to overwrite some properties on fields in the base table. For a list of Table
properties, see Table and Table Extension Properties.
Table extension syntax
tableextension Id MyExtension extends MyTargetTable
{
fields
{
// Add changes to table fields here
}

var
myInt: Integer;
}

Table extension example


This table extension object extends the Customer table object by adding a field ShoeSize , with ID 50116 and the
data type Integer . It also contains a procedure to check if the ShoeSize field is filled in.

tableextension 50115 RetailWinterSportsStore extends Customer


{
fields
{
field(50116;ShoeSize;Integer)
{
trigger OnValidate();
begin
if (rec.ShoeSize < 0) then
begin
message('Shoe size not valid: %1', rec.ShoeSize);
end;
end;
}
}

procedure HasShoeSize() : Boolean;


begin
exit(ShoeSize <> 0);
end;

trigger OnBeforeInsert();
begin
if not HasShoeSize then
ShoeSize := Random(42);
end;
}

See Also
AL Development Environment
Table Overview
Table Object
Table, Table Fields, and Table Extension Properties
Table Keys
Table Keys
2/6/2023 • 12 minutes to read • Edit Online

The database management system, which is SQL Server, uses keys to identify rows in a table. Keys identify the
rows by combining one or more columns of a table. SQL also uses indexes to speed up data retrieval from rows
in a table. This article explains how to create keys and indexes for Business Central tables from AL code.

Keys in AL
In AL, a key definition is a sequence of one or more field IDs from a table. You can define keys in table objects
and table extension objects, depending on the type of key. There are two types of keys: primary and secondary.
Primary keys
A primary key uniquely identifies each record in a table. Every table has a primary key, and there can only
be one primary key per table. Primary keys are defined on table objects only. In SQL, table extension
objects inherit the primary key of the table object they extend (the base table object). So any key that you
define in a table extension object is considered a secondary key.
Secondary keys
Secondary keys create indexes in SQL. They're defined in both table objects and table extension objects.
You can define multiple secondary keys for a single table object and table extension object.
A key in table extension object can include fields from the base table object or the table extension object.
There are some limitations, however. For more information, see Limitations and Restrictions.

Primary keys
The primary key keeps track of data in a table. The primary key is composed of up to 16 fields in a record. The
combination of values in fields in the primary key makes it possible to uniquely identify each record. In AL, the
first key defined in a table object is the primary key. The primary key determines the logical order in which
records are stored, no matter the physical placement of the fields in the table object.
Logically, records are stored sequentially in ascending order and sorted by the primary key. Before adding a new
record to a table, SQL Server checks if the information in the record's primary key fields is unique. If so, it then
inserts the record into the correct logical position. Records are sorted dynamically so the database is always
structurally correct. This sorting allows for fast data manipulation and retrieval.
The primary key is always active. SQL Server keeps the table sorted in primary key order and rejects records
with duplicate values in primary key fields. That's why the values in the primary key must always be unique. It's
not the value in each field in the primary key that must be unique. Instead, it's the combination of values in all
fields that make up the primary key.

NOTE
In the development environment, it's technically possible to create a primary key based on up to 20 fields. However,
because of SQL Server limitations, only the first 16 are used.

Secondary keys
In a table object, any keys defined after the primary key are called secondary keys. All keys defined in a table
extension object are considered secondary keys.
A secondary key is implemented on SQL Server using a structure that is called an index. This structure is like an
index that is used in textbooks. A textbook index alphabetically lists important terms at the end of a book. Next
to each term are page numbers. You can quickly search the index to find a list of page numbers (addresses), and
you can locate the term by searching the specified pages. The index is an exact indicator that shows where each
term occurs in the textbook.
When you define a secondary key and mark it as enabled, an index is automatically maintained on SQL Server.
The index reflects the sorting order that is defined by the key. Several secondary keys can be active at the same
time.
A secondary key can be disabled so that it doesn't occupy database space or use time during updates to
maintain its index. Disabled keys can be re-enabled, although this operation can be time-consuming because
SQL Server must scan the whole table to rebuild the index.
The fields that make up the secondary keys don't always contain unique data. SQL Server doesn't reject records
with duplicate data in secondary key fields. So if two or more records contain identical information in the
secondary key, SQL Server uses the table's primary key to resolve this conflict.

TIP
You can see a list of potential columns that can be indexed and other useful information about them in Business Central
on Database Missing Indexes . For more information on missing indexes, see Missing Indexes in Dynamics 365
Business Central

Unique secondary keys


A key definition includes the Unique property that you can use to create a unique constraint on the table in SQL
Server. A unique key ensures that records in a table don't have identical field values. With a unique key, when
table is validated, the key value is checked for uniqueness. If the table includes records with duplicate values, the
validation fails. Another benefit of unique indexes is providing information to the query optimizer that helps
produce more efficient execution plans.
You can create unique secondary keys that are composed of multiple fields, like with primary keys. In this case,
it's the combination of the values in the secondary key that must be unique. Consider the Customer table, for
example. Suppose you wanted to make sure there are no customers that have the same combination of values
for the Name , Address , and City fields. You could create a unique key for these fields.
Unlike primary keys, it's possible to define multiple unique secondary keys on a table.

NOTE
The Unique property isn't supported in table extension objects.

System keys
There's always a unique secondary key on the SystemId field.
Secondary keys with included fields
INTRODUCED IN: Business Central 2021 release wave 2

With non-clustered secondary keys, you can use the IncludedFields property to add fields that aren't part of the
key itself. In SQL server, these non-key fields correspond to what are called included columns. Using included
fields lets you create indexes that cover more queries, and lets you bypass the maximum number of fields in a
key.
A secondary key with included fields can improve SQL query performance, especially when SQL index contains
all columns in the query, either as key columns or included columns. The performance improves because the
query optimizer can locate all the column values within the index. And, it doesn't access table or clustered index
data, which results in fewer disk I/O operations. For more information about included columns in SQL, see
Create indexes with included columns.
Non-clustered Columnstore keys
INTRODUCED IN: Business Central 2021 release wave 2

Non-clustered columnstore indexes (sometimes referred to as NCCIs) are supported on tables.


With the ColumnStoreIndex property, you create a non-clustered columnstore index on the table in SQL server.
Using a non-clustered columnstore key can improve query performance when doing analytics on large tables.
This index type uses column-based data storage and query processing to achieve gains up to 10 times the query
performance in analytical queries over traditional row-oriented storage. You can also achieve gains up to 10
times the data compression over the uncompressed data size on normal tables.
You can use a non-clustered columnstore index to efficiently run real-time operational analytics on the Business
Central database without the need to define SIFT indexes up front (and without the locking issues that SIFT
indexes sometimes impose on the system.) Whenever you would normally add a SIFT key on fields to do
summation/count operations on, use a non-clustered columnstore key to add all the fields to the index instead.
Example
To illustrate, here's a simple example of replacing two SIFT keys with a single non-clustered columnstore index.
Suppose you already have implemented two SIFT keys:
Key1: "WareHouseId, Color" SumField: "OnStock"
Key2: "WareHouseId, ItemId, Size" SumField: "OnStock"
With a non-clustered columnstore index, you could just have one index defined as:
ColumnStoreIndex = WareHouseId,Color,ItemId,Size,OnStock
For more information, see:
ColumnStoreIndex Property
Columnstore indexes: Overview

Clustered and non-clustered keys


A key definition includes the Clustered property that you use to create a clustered index. A clustered index
determines the physical order in which records are stored in the table. Based on the key value, records are
sorted in ascending order. Using a clustered key can speed up the retrieval of records.
There can be only one clustered index per table. By default the primary is configured as a clustered key.

NOTE
The Clustered property isn't supported in table extension objects.

Sort orders and secondary keys


The following example shows how the primary key influences the sort order when a secondary key is active. The
Customer table includes four entries (records), and the records in the Customer table have two fields: Customer
Number and Customer Name.
The following table includes the key list for the Customer table.

K EY K EY T Y P E DEF IN IT IO N

1 Primary Customer Number

2 Secondary Customer Name

When you sort by the primary key, the Customer table resembles the following table.

C USTO M ER N UM B ER C USTO M ER N A M E

001 Customer C

002 Customer A

003 Customer B

004 Customer C

If you select the secondary key for sorting, then the order is based on the contents of the Customer Name field.
Because the contents of these fields aren't unique, the records must be subsorted according to the primary key.

C USTO M ER N A M E C USTO M ER N UM B ER

Customer A 002

Customer B 003

Customer C 001

Customer C 004

NOTE
The two records that have the same Customer Name value are sorted by Customer Number.

How keys affect performance


Searching for specific data is easier if several keys are defined and maintained for the table that holds the
wanted data. The indexes for each key provide specific views that enable quick and flexible searches. There are
advantages and disadvantages to using many keys, as demonstrated in the following table.

IF Y O U P ERF O RM A N C E IM P RO VES W H EN Y O U P ERF O RM A N C E SLO W S W H EN Y O U

Increase the number of secondary Retrieve data in several different Enter data because indexes for each
keys that are marked as active. sorting sequences because the data is secondary key must be maintained.
already sorted.
IF Y O U P ERF O RM A N C E IM P RO VES W H EN Y O U P ERF O RM A N C E SLO W S W H EN Y O U

Decide to use only a few keys. Enter data because a minimal number Retrieve data. You may have to define
of indexes are maintained. or reactivate the secondary keys to get
the appropriate sorting. Depending on
the size of the database, this operation
can take some time, because the index
must be rebuilt.

The decision whether to use a few or many keys isn't easy. The appropriate keys and the number of active keys
to use is a compromise between maximizing the speed of data retrieval and data updates (operations that insert,
delete, or modify data). In general, it may be worthwhile to deactivate complex keys if they're rarely used.
The overall speed depends on the following factors:
Size of the database.
Number of active keys.
Complexity of the keys.
Number of records in your tables.
Speed of your computer and its hard disk.

Defining new keys


To define keys, add the keys keyword after the fields definition, and then add a key keyword for each key:

keys
{
key(Name1; Fields)
{

}
key(Name2; Fields)
{

}
}

Replace Name with descriptive text that you want to use to identify the key. Replace Field with the name of a
field that you want to use as the key. If you want to include multiple fields in a single key, separate each field
with a comma.
In a table object, the first key keyword defines the primary key. Subsequent key keywords define secondary
keys.

TIP
Starting in Business Central version 18, it is possible to create a table extension that only holds key definitions. You can
utilize this to add keys to tables in the base application or in AppSource extensions, where you don't have ownership of
the table definitions.

The following code illustrates simple examples of a table object and table extension object.
table 50120 MyBaseTable
{
fields
{
field(1; MyBaseField1; Integer)
{
}
field(2; MyBaseField2; Integer)
{
}
}

keys
{
key(PK; MyBaseField1) //primary key
{
Clustered = true;
}
key(Key1; MyBaseField2) //secondary key
{
}
}
}

tableextension 50121 MyBaseTableExt extends MyBaseTable


{
fields
{
field(3; MyExtField1; Integer)
{
}
field(4; MyExtField2; Integer)
{
}
field(5; MyExtField3; Integer)
{
}
}

keys
{
key(ExtKey1; MyExtField1) //secondary key
{
IncludeFields = MyExtField2,MyExtField3;
}
key(ExtKey2; MyBaseField1, MyBaseField2) //secondary key
{
}
// The following key isn't allowed because it contains fields from the base table and the table
extension
//key(ExtKey3; MyBaseField1, MyExtField2)
//{
//}
}
}
tableextension 50122 MyCustomerKeyExt extends Customer
{
// This example illustrates how to use a table extension to add a key on the Customer table from the
base application
keys
{
key(ExtKey1; "No.", "Name", City)
{
}
}
}

Key properties
There are several properties that configure the behavior of a key, such as the Enabled, Clustered, and Unique
properties:

keys
{
key(PrimaryKey; ID)
{
Clustered = true;
}
key(CustomerInfo; Name,Address,City)
{
Unique = true;
}
key(Currency; Currency Code)
{
Enabled = false;
}
}

For a more information about the different key properties, see Key Properties.

Limitations and Restrictions


Keys in table extension objects
In table extension objects, you can define multiple keys, just like in a table object. However, the following
limitations apply:
In Business Central 2020 release wave 2 and earlier, keys in table extension objects can only include fields
from the table extension object itself.
In Business Central 2021 release wave 1 and later, keys in table extension objects can include fields from the
base table object and table extension object. However, a single key can't include fields from both the base
table object and table extension object. In other words, each key must contain fields from either the base
table object or the table extension object.
You can use the same key name in the table extension, unless the key contains fields from the base table
object.
Total number of keys
Up to 40 keys can be associated with a table.
Key modifications
When developing a new version of an extension, be aware of the following restrictions to avoid schema
synchronization errors that prevent you from publishing the new version:
Don't delete primary keys.
Don't add or remove primary key fields, nor change their order.
Don't change properties of existing primary keys.
Don't add more unique keys.
Don't add more clustered keys.
Don't add keys that are fields of the base table.

Identifying keys in code


APPLIES TO: Business Central 2022 release wave 2 and later

When you invoke IntelliSense for table fields, the primary key members are marked with a (PKx) in the
IntelliSense list, where x is a sequential number, which indicates the order of the field in the key. This allows
you to identify the table fields that make up the primary key and the sequency of these fields in the key.

See Also
Key Properties Tables Overview
Table Object
Table Extension Object
SystemId Field
Page Object
2/6/2023 • 2 minutes to read • Edit Online

Pages are the main way to display and organize visual data in Dynamics 365 Business Central. They are the
primary object that a user will interact with and have a different behavior based on the type that you choose.
Pages are designed independently of the device they are to be rendered on, and in this way the same page can
be reused across phone, tablet, and web clients.
The structure of a page is hierarchical and breaks down in to three sections. The first block contains metadata for
the overall page; the type of the page and the source table it is showing data from. The next section; the layout,
describes the visual parts on the page. The final section details the actions that are published on the page.
When developing a solution for Dynamics 365 Business Central, you will follow the code layout for a page as
shown in the page example below, but for more details on the individual controls and properties that are
available, see Page Property Overview.
If you want to, for example, add functionality to a page that already exists in Business Central, you can create a
page extension object that changes an existing page object. For more information, see Page Extension Object.
Depending on how much you want to change on an existing page, you can also create a page customization
object, which offers modifications on actions and layout. For more information, see Page Customization Object.

IMPORTANT
Only pages with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

Snippet support
Typing the shortcut tpage will create the basic layout for a page object when using the AL Language extension
in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Views
Views in Dynamics 365 Business Central are used on list pages to define a different view of the data on a given
page. Views can be defined for Pages, Page Extensions, and Page Customization. For more information, see
Views.

Page example
page 50101 SimpleCustomerCard
{
PageType = Card;
SourceTable = Customer;
ContextSensitiveHelpPage = 'my-feature';

layout
{
area(content)
{
group(General)
{
field("No."; "No.")
{
ApplicationArea = All;
CaptionML = ENU = 'Hello';

trigger OnValidate()
begin
if "No." < '' then
Message('Number too small')
end;
}

field(Name; Name)
{
ApplicationArea = All;
}
field(Address; Address)
{
ApplicationArea = All;
}
}
}
}
actions
{
area(Navigation)
{
action(NewAction)
{
ApplicationArea = All;
RunObject = codeunit "Document Totals";
}
}
}
}

See Also
AL Development Environment
Views
Adding Help Links from Pages, Reports, and XMLports
Page Extension Object
Page, Page Fields, and Page Extension Properties
Page Properties
Developing Extensions
Configure Context-Sensitive Help
Page Extension Object
2/6/2023 • 4 minutes to read • Edit Online

The page extension object extends a Dynamics 365 Business Central page object and adds or overrides the
functionality.
The structure of a page is hierarchical and breaks down into three sections. The first block contains metadata for
the overall page; the type of the page and the source table it is showing data from. The next section; the layout,
describes the visual parts on the page. The final section details the actions that are published on the page.
For more information about the Page and Page Extension objects, see Pages Overview.

IMPORTANT
Only pages with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

IMPORTANT
The API page type should not be extended by creating a page extension object. Instead, create a new API by adding a
page object.

NOTE
Modifying actions in Cue groups on page extensions is not supported.

Snippet support
Typing the shortcut tpageext will create the basic layout for a page extension object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Views
Views in Dynamics 365 Business Central are used on list pages to define a different view of the data on a given
page. Views can be defined for Pages, Page Extensions, and Page Customization. For more information, see
Views.

Using keywords to place actions and controls


You can use the following keywords in the layout section to place and move fields and groups on the page
extension. Similarly, in the actions section, you use these keywords to place actions in the ribbon.

K EY W O RDS SY N TA X A P P L IES TO

addfirst addfirst(Anchor) Anchor : areas and groups

addlast addlast(Anchor) Anchor : areas and groups

addafter addafter(Anchor) Anchor : controls, actions, and groups

addbefore addbefore(Anchor) Anchor : controls, actions, and groups

movefirst movefirst(Anchor; Target1, Anchor : area, group


Target2) Target : list of actions or list of controls

movelast movelast(Anchor; Target1, Anchor : area, group


Target2) Target : list of actions or list of controls

moveafter moveafter(Anchor; Target1, Anchor : controls, actions, and groups


Target2) Target : list of actions or list of controls

movebefore movebefore(Anchor; Target1, Anchor : controls, actions, and groups


Target2) Target : list of actions or list of controls

modify modify(Target) Target : controls, actions, and groups

Example
To modify the existing fields and groups on a page, you use the modify keyword. See the code snippet below
for addlast , modify and action syntax. In the following example, the actions section creates a new group in
the ribbon and places it last in the Creation group.
pageextension 70000020 CustomerCardExtension extends "Customer Card"
{
layout
{
// Adding a new control field 'ShoeSize' in the group 'General'
addlast(General)
{
field("Shoe Size"; ShoeSize)
{
Caption = 'Shoe size';

trigger OnValidate();
begin
if (ShoeSize < 10) then
Error('Feet too small');
end;
}
}

// Modifying the caption of the field 'Address'


modify("Address 2")
{
Caption = 'New Address 2';
}

// Moving the two fields 'CreditLimit' and 'CalcCreditLimitLCYExpendedPct'


// to be the first ones in the 'Balance' group.
movefirst(Balance; CreditLimit, CalcCreditLimitLCYExpendedPct)
}
actions
{
// Adding a new action group 'MyNewActionGroup' in the 'Creation' area
addlast(Creation)
{
group(MyNewActionGroup)
{
action(MyNewAction)
{
Caption = 'My New Action';

trigger OnAction();
begin
Message('My message');
end;
}
}
}
}
}

tableextension 70000020 CustomerTableExtension extends Customer


{
fields
{
// Adding a new table field in the 'Customer' table
field(50100; ShoeSize; Integer) { }
}
}

Page extension examples


In the following example, we use a table extension to extend the Customer table with a new field named
ShoeSize of the datatype Integer. Then we create a page extension object that extends the Customer Card page
object by adding a field control ShoeSize to the General group on the page. The field control is added as the
last control in the group using the addlast method. The example also illustrates how to add a display-only
control to the page. In the actions area, you can see what the syntax looks like for actions that execute triggers
and actions that run objects.

tableextension 50115 RetailWinterSportsStore extends Customer


{
fields
{
field(50116;ShoeSize;Integer)
{
Caption = 'ShoeSize';

trigger OnValidate();
begin
if (rec.ShoeSize < 0) then
begin
message('Shoe size not valid: %1', rec.ShoeSize);
end;
end;
}
}

procedure HasShoeSize() : Boolean;


begin
exit(ShoeSize <> 0);
end;

trigger OnBeforeInsert();
begin
if not HasShoeSize then
ShoeSize := Random(42);
end;
}

pageextension 50110 CustomerCardExtension extends "Customer Card"


{
layout
{
addlast(General)
{
// control with underlying datasource
field("Shoe Size"; ShoeSize)
{
ApplicationArea = All;

trigger OnValidate();
begin
if (ShoeSize < 10) then
Error('Feet too small');
end;
}
// display-only control (without underlying datasource)
field(ShoesInStock; 10)
{
ApplicationArea = All;
Caption = 'Shoes in stock';

}
}

modify("Address 2")
{
Caption = 'New Address 2';
}
}

actions
{
{
addlast(Creation)
{
group(MyActionGroup)
{
Action(MyAction1)
{
ApplicationArea = All;
Caption = 'Hello!';

trigger OnAction();
begin
Message('My message');
end;
}

Action(MyAction2)
{
ApplicationArea = All;

// Run page to test how actions work


RunObject = page "Absence Registration";
}
}
}
}
}

You can reference Report and XMLPort objects and use these objects in the RunObject property, as well as,
declare variables of the types Repor t and XMLPor t and call AL methods on them. This page extension object
extends the Customer List page object by adding two actions; the first action calls the Customer - List report,
the second action calls the Expor t Contact XMLPort.

pageextension 50114 AddCustomerReport extends "Customer List"


{
actions
{
AddLast("&Customer")
{
action("Customer List Report")
{
trigger OnAction();
var
rep : Report "Customer - List";
begin
rep.Run;
end;
}

action("Export Contact List")


{
trigger OnAction();
var
xml : XmlPort "Export Contact";
begin
xml.Run;
end;
}
}
}
}

See Also
Page Object
Views
Page, Page Fields, and Page Extension Properties
Extending Pages Previously Based on the Date Virtual Table Developing Extensions
AL Development Environment
Page Customization Object
2/6/2023 • 2 minutes to read • Edit Online

The page customization object in Dynamics 365 Business Central allows you to add changes to the layout and
actions on page that are accessible for a profile. See Using keywords to place actions and controls for how to
place actions and controls on a page customization object.
The page customization object has more restrictions than the page extension object; when you define a new
page customization object, you cannot add variables, procedures, or triggers.

NOTE
A single page customization can be used with multiple profiles within the same extension. Page customizations only apply
to the RoleCenters they are specified for. In order to view or changes the RoleCenters in the client, go to My Settings >
Role Center .

NOTE
Extension objects can have a name with a maximum length of 30 characters.

NOTE
Modifying actions in Cue groups on page extensions is not supported.

NOTE
The property allowDebugging , which is a setting under resourceExposurePolicy does not apply to page
customizations. Page customizations defined in an extension with allowDebugging set to false can still be copied
using Designer. For more information, see Resource Exposure Policy Setting.

Snippet support
Typing the shortcut tpagecust will create the basic layout for a page customization object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Views
Views in Dynamics 365 Business Central are used on list pages to define a different view of the data on a given
page. Views can be defined for Pages, Page Extensions, and Page Customization. For more information, see
Views.
Page customization example
The following page customization example MyCustomization makes changes to Customer List . By using the
moveafter method, Blanket Orders is moved after the Orders action item. And the modify method is used to
hide the NewSalesBlanketOrder action item.

profile TheBoss
{
Description = 'The Boss';
RoleCenter = "Business Manager Role Center";
Customizations = MyCustomization;
Caption = 'Boss';
}

pagecustomization MyCustomization customizes "Customer List"


{
actions
{
moveafter(Orders; "Blanket Orders")

modify(NewSalesBlanketOrder)
{
Visible = false;
}

}
}

You can use the same page customization on another profile within the same extension package by referencing
its name from the profile definition, for example:

profile TheSalesman
{
ProfileDescription = 'The Boss';
RoleCenter = "Sales Manager Role Center";
Customizations = MyCustomization;
Caption = 'Salesman';
}

See Also
Developing Extensions
AL Development Environment
Page Object
Page Extension Object
Views
Page, Page Fields, and Page Extension Properties
Report Object
2/6/2023 • 4 minutes to read • Edit Online

Reports are used to print or display information from a database. You can use a report to structure and
summarize information, and to print documents, such as sales quotes and invoices.
Creating a report consists of two primary tasks; the first task is to create the underlying data model and the next
is to define the visual layout that displays the data. The report object defines the underlying data model and
specifies which database tables and fields to pull data from. When the report is run, that data is displayed in a
specified layout; the visual layout, which determines the content and format of a report when it's viewed and
printed.
For more information about defining database tables and fields, see Defining a Report Dataset. For more
information about the Report data type, see Report Data Type.
You build the layout of a report by arranging data items and columns, and specifying the general format, such as
text font and size. There are three types of report layouts; client report definition, also called RDL layouts, Word
layouts, and Excel layouts. RDL layouts are defined in Visual Studio Report Designer or Microsoft SQL Server
Reporting Services Report Builder. Word layouts are created using Word. Word layouts are based on a Word
document that includes a custom XML part representing the report dataset. Excel layouts are created in Excel
based on the report dataset, utilizing the Excel capabilities such as sliders, diagrams, charts, pivot tables, and
PowerQuery. One report can contain multiple report layout definitions. For more information, see Defining
Multiple Report Layouts.
If you want to modify an existing report, for example, add new columns, add to the request page, or add a new
layout, you can create a report extension instead. For more information, see Report Extension Object.

TIP
It is possible to use a query object as the data source for a report. This can in many cases improve the performance of
data retrieval when running the report.

Snippet support
Typing the shortcut treport will create the basic layout for a report object when using the AL Language
extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Report example
The following example is a report that prints the list of customers. The report object defines a dataset of
columns from the Customer table. This example defines a report that uses an RDL report layout. For more
information about creating an RDL report layout, see Creating an RDL Layout Report. For more information on
creating a report that uses Word Layout, see Creating a Word Layout Report. For information about creating an
Excel layout, see Creating an Excel Layout Report.
report 50103 "Customer List"
{
CaptionML=ENU='Customer List';
DefaultLayout = RDLC; // if Word use WordLayout property
RDLCLayout = 'MyRDLReport.rdl';

dataset
{
dataitem(Customer;Customer)
{
RequestFilterFields="No.","Search Name","Customer Posting Group";
column(CompanyName;CompanyName)
{
}
column(CurrReport_PageNo;Customer."no.")
{
}
column(Customer_TableCaption_CustFilter;TableCaption + ': ' + CustFilter)
{
}
column(CustFilter;CustFilter)
{
}
column(Customer_No;"No.")
{
}
column(Customer_Customer_Posting_Group;"Customer Posting Group")
{
}
column(Customer_Customer_Disc_Group;"Customer Disc. Group")
{
}
column(Customer_Invoice_Disc_Code;"Invoice Disc. Code")
{
}
column(Customer_Customer_Price_Group;"Customer Price Group")
{
}
column(Customer_Fin_Charge_Terms_Code;"Fin. Charge Terms Code")
{
}
column(Customer_Payment_Terms_Code;"Payment Terms Code")
{
}
column(Customer_Salesperson_Code;"Salesperson Code")
{
}
column(Customer_Currency_Code;"Currency Code")
{
}
column(Customer_Credit_Limit_LCY;"Credit Limit (LCY)")
{
DecimalPlaces=0:0;
}
column(Customer_Balance_LCY;"Balance (LCY)")
{
}
column(CustAddr_1;CustAddr[1])
{
}
column(CustAddr_2;CustAddr[2])
{
}
column(CustAddr_3;CustAddr[3])
{
}
column(CustAddr_4;CustAddr[4])
{
}
}
column(CustAddr_5;CustAddr[5])
{
}
column(Customer_Contact;Contact)
{
}
column(Customer_Phone_No;"Phone No.")
{
}
column(CustAddr_6;CustAddr[6])
{
}
column(CustAddr_7;CustAddr[7])
{
}
column(Customer_ListCaption;Customer_ListCaptionLbl)
{
}
column(CurrReport_PageNoCaption;CurrReport_PageNoCaptionLbl)
{
}
column(Customer_NoCaption;FieldCaption("No."))
{
}
column(Customer_Customer_Posting_GroupCaption;Customer_Customer_Posting_GroupCaptionLbl)
{
}
column(Customer_Customer_Disc_GroupCaption;Customer_Customer_Disc_GroupCaptionLbl)
{
}
column(Customer_Invoice_Disc_CodeCaption;Customer_Invoice_Disc_CodeCaptionLbl)
{
}
column(Customer_Customer_Price_GroupCaption;Customer_Customer_Price_GroupCaptionLbl)
{
}
column(Customer_Fin_Charge_Terms_CodeCaption;FieldCaption("Fin. Charge Terms Code"))
{
}
column(Customer_Payment_Terms_CodeCaption;Customer_Payment_Terms_CodeCaptionLbl)
{
}
column(Customer_Salesperson_CodeCaption;FieldCaption("Salesperson Code"))
{
}
column(Customer_Currency_CodeCaption;Customer_Currency_CodeCaptionLbl)
{
}
column(Customer_Credit_Limit_LCYCaption;FieldCaption("Credit Limit (LCY)"))
{
}
column(Customer_Balance_LCYCaption;FieldCaption("Balance (LCY)"))
{
}
column(Customer_ContactCaption;FieldCaption(Contact))
{
}
column(Customer_Phone_NoCaption;FieldCaption("Phone No."))
{
}
column(Total_LCY_Caption;Total_LCY_CaptionLbl)
{
}

trigger OnAfterGetRecord();
begin
CalcFields("Balance (LCY)");
FormatAddr.FormatAddr(
CustAddr,Name,"Name 2",'',Address,"Address 2",
CustAddr,Name,"Name 2",'',Address,"Address 2",
City,"Post Code",County,"Country/Region Code");
end;

}
}

requestpage
{
SaveValues=true;
ContextSensitiveHelpPage = 'my-feature';
layout
{
}

actions
{
}
}

labels
{
LabelName = 'LabelText', Comment = 'Foo', MaxLength = 999, Locked = true;
}

trigger OnPreReport();
var
CaptionManagement : Codeunit 42;
begin
CustFilter := CaptionManagement.GetRecordFiltersWithCaptions(Customer);
end;

var
FormatAddr : Codeunit 365;
CustFilter : Text;
CustAddr : ARRAY [8] OF Text[50];
Customer_ListCaptionLbl : Label 'Customer - List';
CurrReport_PageNoCaptionLbl : Label 'Page';
Customer_Customer_Posting_GroupCaptionLbl : Label 'Customer Posting Group';
Customer_Customer_Disc_GroupCaptionLbl : Label 'Cust./Item Disc. Gr.';
Customer_Invoice_Disc_CodeCaptionLbl : Label 'Invoice Disc. Code';
Customer_Customer_Price_GroupCaptionLbl : Label 'Price Group Code';
Customer_Payment_Terms_CodeCaptionLbl : Label 'Payment Terms Code';
Customer_Currency_CodeCaptionLbl : Label 'Currency Code';
Total_LCY_CaptionLbl : Label 'Total (LCY)';
}

TIP
From the Business Central client, you can export report results as raw data to a Microsoft Excel file. The file contains all
columns of the dataset, but without the layout applied. Use the file to help validate that the report returns the expected
data, and to ensure that the report layout controls match the dataset value types. To export a report, run the report and
select the Send to > Microsoft Excel Document (data only) on the request page. For more information, see
Working with Reports - Send to Excel.

Schedule reports
It's possible to schedule a report to run at your desired date and time by using AllowScheduling property. By
setting the property to true, you'll get the Schedule action button to set the date and time for your report. To
learn more about scheduling a report, see AllowScheduling Property and Schedule a report.
See also
Report Extension Object
Request Pages
Report Properties
Creating an RDL Layout Report
Creating a Word Layout Report
Adding Help Links from Pages, Reports, and XMLports
Page Extension Object
Page Properties
Developing Extensions
AL Development Environment
Profile Object
2/6/2023 • 2 minutes to read • Edit Online

The profile object in Dynamics 365 Business Central allows you to build an individual experience for each user
profile. The Profile object performs a validation to check whether the specified role center page exists, and page
customization objects exists, when you define a new profile object. On a page customization you can add
changes to the page layout, and actions; but you cannot add variables, procedures, or triggers.

NOTE
Page customizations only apply to the RoleCenter they are specified for. In order to see them, in Dynamics 365 Business
Central under My Settings , Role Center change to the specific RoleCenter that a page customization is defined for.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

NOTE
The property allowDebugging , which is a setting under resourceExposurePolicy does not apply to page
customizations. Page customizations defined in an extension with allowDebugging set to false can still be copied
using Designer. For more information, see Resource Exposure Policy Setting.

Snippet support
Typing the shortcut tprofile will create the basic layout for a profile object when using the AL Language
extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Profile example
The following profile object example creates a profile for the MyRoleCenter Role Center, which is available in the
Role Explorer in the UI and available to end-users. The profile also depends on the customization
MyCustomization and modifies the layout of the Customer List to make the Name field invisible using the
modify method. For more information, see Profile Properties.
profile MyProfile
{
Description = 'Some internal comment that only the Dev can see';
Caption = 'My User-friendly Name';
ProfileDescription = 'A detailed description of who is this profile for, why/how to use it (etc)';
RoleCenter = MyRoleCenter;
Enabled = true;
Promoted = true;
Customizations = MyCustomization;
}

pagecustomization MyCustomization customizes "Customer List"


{
layout
{
modify(Name)
{
Visible = false;
}
}
}

See Also
AL Development Environment
Developing Extensions
Pages Overview
Page Customization Object
Codeunit Object
2/6/2023 • 2 minutes to read • Edit Online

A codeunit is a container for AL code that you can use in many application objects. You typically implement
business logic in codeunits and call the codeunit from the object that needs to perform that specific logic.

Snippet support
Typing the shortcut tcodeunit will create the basic layout for a codeunit object when using the AL Language
extension in Visual Studio Code.

Codeunit example
This codeunit example checks whether a given customer has registered a shoe size. If not, the customer is
assigned a shoe size of 42.
The codeunit can be used both as a direct call to codeunit.run(customer) or as a call to the procedure inside the
codeunit createcustomer.CheckSize(customer) .

codeunit 50113 CreateCustomer


{
TableNo = Customer;
trigger OnRun();
begin
CheckSize(Rec);
end;
procedure CheckSize(var Cust : Record Customer)
begin
if not Cust.HasShoeSize() then
Cust.ShoeSize := 42;
end;
}

See Also
Developing Extensions
Table Extension Object
Page Extension Object
AL Development Environment
XML Comments in Code
Query Object
2/6/2023 • 4 minutes to read • Edit Online

Business Central query objects enable you to retrieve records from one or more tables and then combine the
data into rows and columns in a single dataset. Query objects can also perform calculations on data, such
finding the sum or average of all values in a column of the dataset.
There are two types of query objects: normal and API. This article describes normal query objects, which can be
used to display data in the user interface. API query objects are used to generate web service endpoints and
cannot be displayed in the user interface. For information about creating a query of the type API, see API Query
Type.

Creating a query object


A query object is comprised mainly of two different types of elements: dataitems and columns. A dataitem
specifies the table to retrieve records from. A column specifies a field of the table to include in the resulting
dataset of a query. The basic steps to create a query object are as follows:
1. Add the query keyword, followed by the elements control.
2. Build the dataset by adding dataitem controls and column controls within the elements control.
The hierarchy of the dataitem and column controls is important because it will determine the sequence
in which data items are linked, which in turn will control the results. Working from top-to-bottom, you
start by adding the dataitem control for first table that you want in the dataset, then add column
controls for each table field that you want to include in the dataset. For the next table, you add another
dataitem control that is embedded within the first dataitem control, then add column controls as
needed. You continue this pattern for additional tables and fields.
3. When you have specified the dataitem and column elements, create links and joins between the
dataitem elements.

Dataitem links and joins determine which records to include in the dataset based on the values of a
common field between dataitems. You set a link between one or more fields of the dataitem tables with
the DataItemLink Property and you define the type of the link using the SQLJoinType Property. Both
properties must be set on the lower dataitem of the query object. For more information, see Linking and
Joining Data Items.
The following shows the basic structure of a query object.
query ID Name
{

elements
{
dataitem(DataItem1; Table1)
{
column(Column1; Field1)
{
}
column(Column2; Field2)
{
}
dataitem(DataItem2; Table2)
{
// Sets a link between FieldY of Table2 and FieldX of Table1.
DataItemLink = FieldY = DataItem1.FieldX;
//The dataset contains records from Table1 and Table2 where a match is found between FieldY
and FieldX.
SqlJoinType = InnerJoin;

column(Column1; Field1)
{
}
dataitem(DataItem3; Table3)
{
DataItemLink = FieldZ = DataItem2.FieldY;
SqlJoinType = InnerJoin;
column(Column1; Field1)
{
}
}
}
}
}
}

NOTE
Extension objects can have a name with a maximum length of 30 characters.

Snippet support
Typing the shortcut tquery will create the basic layout for a Query object when using the AL Language
extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Query example
The following example shows a query that displays a list of customers with sales and profit figures. The query
primarily retrieves fields from the Customer table, but also displays fields from the Salesperson Purchaser
and Countr y Region tables.
The query also uses the DataItemLink property to create a link between the Customer table, Salesperson
Code field and the Salesperson Purchaser table, Code fields and a link between the Customer table,
Countr y/Region Code field and the Countr y/Region table, Code field.

query 50102 "Top Customer Overview"


{
QueryType = Normal;
Caption = 'Top Customer Overview';

DataAccessIntent = ReadOnly; // use this to read data from the secondary database replica to speed up
performance

elements
{
dataitem(Customer; Customer)
{
column(Name; Name)
{
}
column(No; "No.")
{
}
column(Sales_LCY; "Sales (LCY)")
{
}
column(Profit_LCY; "Profit (LCY)")
{
}
column(Country_Region_Code; "Country/Region Code")
{
}
column(City; City)
{
}
column(Global_Dimension_1_Code; "Global Dimension 1 Code")
{
}
column(Global_Dimension_2_Code; "Global Dimension 2 Code")
{
}
column(Salesperson_Code; "Salesperson Code")
{
}
dataitem(Salesperson_Purchaser; "Salesperson/Purchaser")
{
DataItemLink = Code = Customer."Salesperson Code";
column(SalesPersonName; Name)
{
}
dataitem(Country_Region; "Country/Region")
{
DataItemLink = Code = Customer."Country/Region Code";
column(CountryRegionName; Name)
{
}
}
}
}
}
}
IMPORTANT
You cannot run a query that gets data from both the application database and the business data database. This also
applies to single-tenant deployments so that you do not have to rewrite queries if you decide to export the application.
For a description of which tables are considered part of the application database, see Separating Application Data from
Business Data.

See Also
Linking and Joining Data Items
Aggregating Data in Query Objects
Query Objects and Performance
Query Properties
Query DataAccessIntent
Developing Extensions
AL Development Environment
API Query Type
XMLport Object
2/6/2023 • 2 minutes to read • Edit Online

XMLports are used to export and import data between an external source and Dynamics 365 Business Central.
Sharing data between different computer systems is seamless when it is shared in an XML format. Working with
XML files can be tedious so the details of how the XML file is handled are encapsulated in XMLports.
To use an XMLport to import or export data, you first create an XMLport object. Once created, you can run the
XMLport from a page or codeunit object.
You can design XMLports to include a request page, which is a dialog box that enables the user to set a filter on
the data, sort the data, or choose whether to export or import the data. For more information about request
pages, see Request Pages.

XMLport example
The following example shows a page extension of the Permission Sets page that adds an action to the
specified page calling the XMLport Expor tPermissionSet . The XMLport exports the permission set data to an
XML file.

pageextension 50111 PermissionSetExporter extends "Permission Sets"


{
actions
{
addafter(Permissions)
{
action(ExportPermissionSet)
{
Promoted = true;
PromotedCategory = New;
trigger OnAction();
begin
Xmlport.Run(50112, false, false);
end;
}
}
}
}

xmlport 50112 ExportPermissionSet


{
Format = xml;

schema
{
textelement(PermissionSets)
{
tableElement(PSet; "Aggregate Permission Set")
{
SourceTableView = WHERE ("App Name" = FILTER (<> ''));
XmlName = 'PermissionSet';
fieldattribute(RoleID; pset."Role ID") { }
fieldattribute(RoleName; pset.Name) { }
tableelement(P; "Tenant Permission")
{
XmlName = 'Permission';
LinkTable = pset;
LinkFields = "Role ID" = FIELD ("Role ID");
textelement(ObjectType)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Object Type";
ObjectType := format(int);
end;
}
textelement(ObjectID)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Object ID";
ObjectID := format(int);
end;
}
textelement(ReadPermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Read Permission";
ReadPermission := format(int);
end;
}
textelement(InsertPermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Insert Permission";
InsertPermission := format(int);
end;
}
textelement(ModifyPermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Modify Permission";
ModifyPermission := format(int);
end;
}
textelement(DeletePermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Delete Permission";
DeletePermission := format(int);
end;
}
textelement(ExecutePermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Execute Permission";
ExecutePermission := format(int);
end;
end;
}
textelement(SecurityFilter)
{
trigger onbeforePassvariable();
begin
SecurityFilter := format(p."Security Filter");
end;
}
}
}
}
}
}

See Also
Developing Extensions
AL Development Environment
XMLport Overview
Using Namespaces with XMLports
Page Extension Object
Report Object
Control Add-In Object
2/6/2023 • 4 minutes to read • Edit Online

The control add-in object allows you to add custom functionality to Dynamics 365 Business Central. A control
add-in is a custom control, or visual element, for displaying and modifying data within an iframe or a page. For
example, a control add-in can display the content of a webpage, visualize data as a chart or on a map, or host a
custom web application. Control add-ins can exchange data with the Dynamics 365 server on various data types
and respond to user interaction to raise events that execute additional AL code.

Control add-in properties


In the control add-in definition, you must set the Scripts property to include scripts in the control add-in. The
scripts could be local files in the package or references to external files using the HTTP or the HTTPS protocol.
With the StartupScript property, you can call a special script that runs when the page you've implemented the
control add-in on, is loaded. These settings initialize the control add-in. With the Images and StyleSheet
properties, you can specify additional styling to the control add-in. For more information about some of the
control add-in properties, see:
Images
Scripts
StartupScript
StyleSheets
RecreateScript
RefreshScript

Sizing of the control add-in


Control add-ins can either have fixed dimensions or dynamically adapt to the available space on the screen. By
controlling the sizing of an add-in, you ensure the add-in and the surrounding content on the page remain
optimal on smaller display targets such as the phone or when users resize the browser. The following properties
are available for you to specify how the sizing of the control add-in should behave.
HorizontalShrink
HorizontalStretch
MinimumHeight
MinimumWidth
MaximumHeight
MaximumWidth
RequestedHeight
RequestedWidth
VerticalShrink
VerticalStretch

Control add-in considerations and limitations


Designing control add-ins that provide the best possible experience can require some additional planning,
design, and implementation. The following considerations and limitations will help you design add-ins that look
and feel seamlessly integrated with both Dynamics 365 Business Central online and on-premises.
Respond to touch events so that mobile users or users on devices supporting touch input can also use
the add-in.
Design content that is responsive and can flow, resize, or reorganize naturally based on the available
space.
Consider the accessibility needs of users, for example by implementing keyboard access and support for
screen readers.
Use the Style guidelines to apply a choice of colors, typefaces, and font sizes that match that of Dynamics
365 Business Central. For more information, see Control Add-in Style Guide.
Provide language translation and other localizations that match the current user language in Dynamics
365 Business Central.
In extensions for Business Central online, don't reference font files in stylesheets, because the fonts won't
display in client. Instead, do one of the following:
Reference the font files from some other source such as a public or private CDN.
Base64 encode the fonts and include the encoded fonts in the CSS file.
For more information about writing efficient code for contron add-ins, see Control Add-In Best Practices.

Control add-in syntax example


The following control add-in syntax shows how to implement small customizations of the layout and
functionality of a page.

// The controladdin type declares the new add-in.


controladdin SampleAddIn
{
// The Scripts property can reference both external and local scripts.
Scripts = 'https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-debug.js',
'main.js';
// The StartupScript is a special script that the web client calls once the page is loaded.
StartupScript = 'startup.js';

// Specifies the StyleSheets that are included in the control add-in.


StyleSheets = 'skin.css';

// Specifies the Images that are included in the control add-in.


Images = 'image.png';

// The procedure declarations specify what JavaScript methods could be called from AL.
// In main.js code, there should be a global function CallJavaScript(i,s,d,c)
{Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('CallBack', [i, s, d, c]);}
procedure CallJavaScript(i: integer; s: text; d: decimal; c: char);

// The event declarations specify what callbacks could be raised from JavaScript by using the webclient
API:
// Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('CallBack', [42, 'some text', 5.8, 'c'])
event Callback(i: integer; s: text; d: decimal; c: char);
}

The controladdin object is then invoked as a usercontrol on a page called PageWithAddIn .


page 50130 PageWithAddIn
{
layout
{
area(Content)
{
// The control add-in can be placed on the page using usercontrol keyword.
usercontrol(ControlName; SampleAddIn)
{

ApplicationArea = All;

// The control add-in events can be handled by defining a trigger with a corresponding
name.
trigger Callback(i: integer; s: text; d: decimal; c: char)
begin
Message('Got from js: %1, %2, %3, %4', i, s, d, c);
end;
}
}
}

actions
{
area(Creation)
{
action(CallJavaScript)
{
ApplicationArea = All;

trigger OnAction();
begin

// The control add-in methods can be invoked via a reference to the usercontrol.
CurrPage.ControlName.CallJavaScript(5, 'text', 6.3, 'c');
end;
}
}
}
}

Loading static resources using AJAX requests


You can design a control add-in to load static resources from the add-in package by using AJAX requests. For
example, the control add-in could load HTML content and inject it into add-in's HTML structure. In this case, you
must use the withCrendentials property set to true in the AJAX request. Otherwise, the request won't contain
the necessary context and important cookies required by the Business Central service, and it may fail in
production. This concept is illustrated in the following examples.
Wrong:

$.get(url).done(function(response) { } );

Correct:
$.ajax({
url: url,
xhrFields: {
withCredentials: true
}
)).done(function(data) {
$("#controlAddIn").text(data);
});

See Also
AL Development Environment
Developing Extensions
Asynchronous Considerations for Control Add-ins
Control Add-In Best Practices
InvokeExtensibility Method
GetImageResource Method
GetEnvironment Method
Pages Overview
Page Extension Object
Page Customization Object
Entitlement Object
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

The entitlement object in Business Central describes which objects in Business Central a customer is entitled to
use according to the license that they purchased or the role that they have in AAD.
An entitlement consists of a number of PermissionSet Objects put together to constitute a set of meaningful
permissions for a user. An entitlement can only include permission set objects which reference the objects that
are included within the same app. This is to ensure that the entitlements included with one app cannot alter or
redefine the entitlements included with another app.
Entitlements can only be used with the online version of Business Central.

NOTE
In the current version of Business Central entitlements can only be included with Microsoft apps (enforced by the
AppSource cop rules and the technical validation checks that we run for the apps submitted to AppSource). These objects
will become available for the ISV apps when we introduce ability to monetize AppSource apps in one of our future
releases.

Snippet support
Typing the shortcut tentitlement will create the basic layout for an entitlement object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Entitlement examples
This example illustrates a simple entitlement object with the Type property set to Role , which means that the is
entitlement is associated with an AAD role. When Type is set to Role , the RoleType property is used to
distinguish between local and delegated assignments of the role, in this case it is Delegated . The
ObjectEntitlements property defines the list of permissions that the entitlement includes.

entitlement BC_Role_Delegated
{
Type = Role;
RoleType = Delegated;
Id = '1a2aaaaa-3aa4-5aa6-789a-a1234567aaaa';
ObjectEntitlements =
”D365 BUS PREMIUM - BaseApp”;
}

An example of an entitlement where Type is PerUserServicePlan :


entitlement BC_PerUserServicePlan
{
Type = PerUserServicePlan;
Id = '1a2aaaaa-3aa4-5aa6-789a-a1234567aaaa';

ObjectEntitlements = "D365 BASIC";

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Extension Object
Permission Set Object
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

The permission set object in Business Central describes permissions on objects. Permission sets are building
blocks used to compose assignable permission sets and entitlements. Assignable permission sets are
permissions that an admin can assign to users in Business Central, using the Permission Sets page. An
entitlement is a collection of permission sets that constitute a set of meaningful permissions for a user.
Some permission sets can be non-assignable, meaning that they aren't discoverable and assignable in the UI in
Business Central, instead they can be used as building blocks to compose functional assignable permission sets.
For information about which permissions can be assigned to objects, see Permissions on Database Objects.

Designing with cautiousness


If a permission set is extended through AL, the extension will make additive changes to the permission set. This
behavior means an extension can provide elevated privileges to an otherwise limited set of permissions.
Building permission sets that can be extended must be done carefully with this behavior in mind.

Snippet support
Typing the shortcut tpermissionset will create the basic layout for a permission set object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Generate permission set for an object


APPLIES TO: Business Central 2022 release wave 2 and later

When adding new AL objects, it's easy to forget to update the permissions. With the
al.generatePermissionSetForExtensionObjects command, you can generate or update a permission file for the
active project in Visual Studio Code. Choose to create a new permission file or select an existing file to make
updates to. For more information, see AL Language Extension Configuration.

Permission set example


The following example illustrates a permission set Sales Person with permissions given to data in tables, each
with different level of access. The Assignable property is set to true , which allows the permission set to be
assigned to a user. The Permissions property is set to the list of objects to give permissions to. The RIMD access
assigned to data in the Customer table provides full access, whereas, for example, access is limited for data in
the Currency table only allowing full read and modify permission.
NOTE
The name of the permissionset object is limited to 20 characters when the Assignable property is set to true .
Otherwise, it's limited to 30 characters. Exceeding the limit will throw the diagnostic Compiler Error AL0305.

permissionset 50134 "Sales Person"


{
Assignable = true;
Caption = 'Sales Person';

Permissions =
tabledata Customer = RIMD,
tabledata "Payment Terms" = RMD,
tabledata Currency = RM,
tabledata "Sales Header" = RIM,
tabledata "Sales Line" = RIMD;
}

The following example of a permission set illustrates assigned permissions to run codeunits. With the
IncludedPermissionSets property, we specify that the permission set Sales Person is also included in
MyPermissionSet .

permissionset50135MyPermissionSet
{
Assignable = true;
Caption = 'My PermissionSet';
IncludedPermissionSets= "Sales Person";

Permissions=
tabledataVendor=RIm,
codeunit SomeCode =x,
codeunit AccSchedManagement=X;
}

You can also use the ExludedPermissionSets property to exclude permissions defined in other permission sets.
To learn more, see Composing Permission Sets From Other Permission Sets.

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Extension Object
Permissions on Database Objects
Assignable Property
IncludedPermissionSets
Permissions Property
Permission Set Extension Object
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

The permission set extension object in Business Central adds permissions to an existing permission set defined
in AL. A permission set extension object cannot remove permissions from an existing permission set, it can only
add permissions. If you, for example, add an extension to Business Central, you can use permission set extension
objects to grant permissions to the objects in your extension. This means that the admin of Business Central
does not have to assign additional permission sets to the users, because that automatically happens when the
extension is installed, and the permissions go away if the extension is uninstalled.
For information about which permissions can be assigned to objects, see Permissions on Database Objects.

Designing with cautiousness


If a permission set is extended through AL, that extension will make additive changes to the permission set. This
means that an extension can provide elevated privileges to an otherwise limited set of permissions. Building
permission sets that can be extended must be done carefully with this in mind.

Snippet support
Typing the shortcut tpermissionsetextension will create the basic layout for a permission set extension object
when using the AL Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Permission set example


The following permission set extension example extends the Sales Person permission set by adding direct
insert and delete permissions to the Currency table data.

permissionsetextension 50140 "Extended Sales Doc" extends "Sales Person"


{
Permissions = tabledata Currency = ID;
}

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Object
Permissions on Database Objects
Assignable Property
Permissions Property
Create Test Codeunits and Test Methods
2/6/2023 • 2 minutes to read • Edit Online

In Dynamics 365 Business Central, you can create test codeunits and then test methods in the test codeunits.
Test codeunits are codeunits that have the SubType Property set to Test . You write tests as Al code in the
methods inside of the test codeunits. There are three types of methods that you can add in a test codeunit: test,
handler, and normal. Each method type is used for a specific purpose and behaves differently. When a test
codeunit runs, it runs the OnRun trigger, and then runs each test method in the codeunit.
By default, each test method runs in a separate database transaction, but you can use the TransactionModel
Attribute on test methods and the TestIsolation Property on test runner codeunits to control the transactional
behavior.
The results of a test codeunit and of the individual test methods are displayed in a message window, but you can
use the OnAfterTestRun Trigger on a test runner codeunit to capture the results. The outcome of a test method is
either SUCCESS or FAILURE. If any error is raised by either the code that is being tested or the test code, then the
global outcome of the test codeunit is FAILURE and the error is included in the results log file.
The difference between a normal codeunit and a test codeunit is their execution at runtime. When a normal
codeunit is run, if one of its methods fails, then the codeunit is terminated. When a test codeunit is run, even if
the outcome of one test method is FAILURE, the next test methods are still running.
The methods in a test codeunit can be one of the following types:

TYPE DESC RIP T IO N

Test method You use test methods that include AL code that tests the
business logic in the application, where each method covers
a transaction. You declare the Test Attribute on the method.

Handler method You use handler methods to automate tests by handling


instances when user interaction is required by the code that
is being tested by the test method. In these instances, the
handler method is run instead of the requested user
interface. The handler method should simulate the user
interaction for the test case, such as validating messages,
making selections, or entering values. You declare a handler
type attribute on the method. For more information, see
Create Handler Methods

Normal method You use normal methods to structure the test code by using
the same design practices and principles as methods in other
codeunits of the application. You declare the Normal
Attribute on the method.

See Also
Testing the Application
Create Test Runner Codeunits
2/6/2023 • 2 minutes to read • Edit Online

You can create test runner codeunits to manage the execution of test codeunits and to integrate with test
management or test reporting frameworks. By integrating with a test management framework, you can
automate your tests and enable them to run unattended.
To create a test runner codeunit, create a codeunit and set the SubType Property to TestRunner .
To specify what changes in the database you want to roll back after the tests in the test runner codeunit execute,
set the TestIsolation Property.
Test runner codeunits include the following triggers:
OnRun Trigger
OnBeforeTestRun Trigger
OnAfterTestRun Trigger
In the OnRun trigger, you'll enter the code to run the codeunits. It runs when you execute the codeunit and
before the test methods run. You can use the OnBeforeTestRun and the OnAfterTestRun triggers to perform
preprocessing and postprocessing, such as initialization or logging test results. If you implement the
OnBeforeTestRun trigger, then it executes before each test method executes. If you implement the
OnAfterTestRun trigger, then it executes after each test method executes and also suppresses the automatic
display of the results message.

WARNING
The OnBeforeTestRun and OnAfterTestRun triggers always run in their own transactions, regardless of the value of
the TestIsolation Property, the value of the TransactionModel Property, or the outcome of a test method.

Example
This sample codeunit runs three test codeunits in the automated application test libraries.

codeunit 50101 TestRunnerCodeunit


{
Subtype = TestRunner;

trigger OnRun()
begin
Codeunit.RUN(Codeunit::"ERM Vendor Statistics");
Codeunit.RUN(Codeunit::"ERM Sales Quotes");
Codeunit.RUN(Codeunit::"ERM Dimension");

end;
}

You may want to define your test suite in a table and then write code in the test runner codeunit to iterate
through the items in the table. And then run each test codeunit. In that case, you can make use of the following
example.
codeunit 50102 TestRunnerCodeunit
{
Subtype = TestRunner;

trigger OnRun()
var
EnabledTestCodeunit: Record "CAL Test Enabled Codeunit";
Object: Record "Object";
begin
if EnabledTestCodeunit.FINDSET then
repeat
if Object.GET(ObjectType::Codeunit, '', EnabledTestCodeunit."Test Codeunit ID") then
CODEUNIT.RUN(EnabledTestCodeunit."Test Codeunit ID");
until EnabledTestCodeunit.NEXT = 0

end;
}

See Also
Testing the Application
Triggers Overview
2/6/2023 • 2 minutes to read • Edit Online

This section describes the triggers that are available to developers in Business Central.

TIP
If you already know the name of, for example, a data type, method, property, or trigger, use the Filter by title field in the
upper left corner, above the table of contents to find the topic faster. Otherwise, you can scan the table of contents to find
it.

Triggers activate a method when a certain event occurs. When AL methods are run because of a predefined
event on either an object or a control, the event triggers the method. Together the event and method make a
trigger.
Triggers are useful for doing calculations and validations. Compared to properties, they provide a more diverse,
effective way of doing such operations. For example, you can use triggers in reports to control how data is
selected and retrieved.

Coding triggers
There are different triggers for the various AL object types. Some triggers are set on the object-level, while
others are set on the controls. For example, a table has some triggers on the table object and other triggers on
field controls. Or consider reports, which have some triggers on the report object and some on the data items.
Trigger are typically added at the end the code block for the object or control. Triggers have the following syntax:

trigger OnWhat()
var
myVariable: type;
begin
// Custom code
end;

Snippet support
Typing the shortcut ttrigger will create the basic layout for a trigger when using the AL Language extension in
Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Example
The following example shows the basic trigger layout for a table object.
table 50100 MyTable
{

fields
{
field(1;MyField; Integer)
{
// Field triggers
trigger OnLookup()
var
myInt: Integer;
begin

end;
}
}

keys
{
key(Key1; MyField)
{
Clustered = true;
}
}

var
myInt: Integer;

// Table object triggers


trigger OnInsert()
begin

end;

trigger OnModify()
begin

end;

trigger OnDelete()
begin

end;

trigger OnRename()
begin

end;
}

See Also
Methods
Properties
AL Error Handling
2/6/2023 • 2 minutes to read • Edit Online

The AL language has many error handling features, which can help you deal with unexpected situations that
occur when code is run. This section contains articles about using these methods in AL to handle errors that
occur during code execution, while making sure that your application has a consistent user interface.
The following articles introduce error handling in AL:
Handling Errors using Try Methods
Collecting Errors
Progress Windows, Message, Error, and Confirm Methods

Error handling methods in AL


For examples of using different error handling methods in AL, see the following table:

M ET H O D DESC RIP T IO N

ClearLastError Method Removes the last error message from memory.

Dialog Data Type Represents a dialog window.

Error Method Displays an error message and ends the execution of AL


code.

ErrorInfo Data Type Contains a set of methods that helps identify errors, classify
these errors, send errors to telemetry and display UI
messages. Go to the data type article for an overview.

System Data Type Is a complex data type and contains multiple methods for
getting and classifying errors.

GetLastErrorCallStack Method Gets the call stack from where the last error occurred.

GetLastErrorCode Method Gets the classification of the last error that occurred.

GetLastErrorObject Method Gets the last System.Exception object that occurred.

GetLastErrorText Method Gets the last error that occurred in the debugger.

TIP
If you already know the name of a data type, use the Filter by title field in the upper left corner, above the table of
contents to find the topic faster.

Error handling strategies


For examples of different error handling strategies, see the following table:
IF Y O U WA N T TO. . . T H EN USE

Run a code unit and decide to do something if an error if not Codeunit.run() . For more information, see
occurs. Codeunit.Run return value

Check for an error and show an error dialog to the user. Dialog.Error(Message: ErrorInfo) . For more
information, see Error Method.

Check for an error and show an error dialog to the user with Using the ErrorInfo Data Type with the Error Method
added support information.

Do bulk validations in AL and not show an error dialog for Collecting Errors
each of them to the user.

Catch errors raised by other AL methods Handling Errors using Try Methods

Catch errors/exceptions that are thrown during .NET Handling .NET Exceptions using Try Methods
framework interoperability operations (on-premises only).

Log an error that happens within a database transaction Either log the error in a new session using a background
(that rollback) session, or use Session.LogMessage to log the error to
telemetry.

See also
AL Control Statements
AL Development Environment
Handling Errors using Try Methods
2/6/2023 • 2 minutes to read • Edit Online

Try methods in AL enable you to handle errors that occur in the application during code execution. For example,
with try methods, you can provide more user-friendly error messages to the end user than those that are
thrown by the system.

NOTE
Try Methods are available from runtime version 2.0.

Behavior and usage


The main purpose of try methods is to catch errors/exceptions that are thrown by Business Central or
exceptions that are thrown during .NET Framework interoperability operations. Try methods catch errors similar
to a conditional Codeunit. Except for the try method, the Run method call doesn't require that write transactions
are committed to the database, and changes to the database that are made with a try method aren't rolled back.
Database write transactions in try methods
Because changes made to the database by a try method aren't rolled back, you shouldn't include database write
transactions within a try method. By default, the Business Central Server configuration prevents you from doing
this. If a try method contains a database write transaction, a runtime error occurs.
Handling errors with a return value
A method that is designated as a try method has a Boolean return value (true or false ), and has the
construction OK:= MyTrymethod . A try method can't have a user-defined return value.
If a try method call doesn't use the return value, the try method operates like an ordinary method, and
errors are exposed as usual.
If a try method call uses the return value in an OK:= statement or a conditional statement such as
if-then , errors are caught. The try method returns true if no error occurs; false if an error occurs.

NOTE
The return value isn't accessible within the try method itself.

Getting details about errors


You can use the GetLastErrorText method to obtain errors that are generated by Business Central. To get details
of exceptions that are generated by .NET Framework objects, you can use the GetLastErrorObject method to
inspect the Exception.InnerException property.

Creating a try method


To create a try method, add a method in the AL code of an object such as a codeunit, and then set the
TryFunction Attribute.

Example 1
The following simple example illustrates how the try method works. First, create a codeunit that has a local
method MyTrymethod . Add the following code on the OnRun trigger and MyTrymethod method.

trigger OnRun()
begin
MyTrymethod;
message('Everything went well');
end;

local procedure MyTryMethod()


begin
error('An error occurred during the operation');
end;

When you run this codeunit, the execution of the OnRun trigger stops. The error message
An error occurred during the operation is thrown in the UI.

Now, set the TryFunction Attribute of the MyTrymethod method. Then, add code to the OnRun trigger to handle
the return value of the try method:

[TryFunction]
local procedure MyTryMethod()
begin
error('An error occurred during the operation');
end;

trigger OnRun()
begin
if MyTryMethod then
message('Everything went well')
else
message('Something went wrong')
end;

When you run the codeunit, instead of stopping the execution of the OnRun trigger when the error occurs, the
error is caught and the message Something went wrong is returned.

See Also
AL Simple Statements
Collecting Errors
2/6/2023 • 4 minutes to read • Edit Online

This article explains how to write AL code that captures multiple errors and displays them in the user interface.
Referred to as collectible errors, this feature can simplify validation scenarios. Specifically, scenarios where users
are presented with a list of things to fix.
Normally, when an error occurs in a procedure, the procedure stops on the first error it meets. Using collectable
errors essentially postpones error handling to the end of the procedure call. AL code execution won't stop on
errors. But instead, it continues until the end and gathers errors as they occur.

Collectible errors API


AL includes several methods, properties, and attributes that are designed specifically for the collectable errors
feature.
Error information
The following methods are available on the ErrorInfo data type for defining information about errors. These
methods can be invoked using property access syntax.

M ET H O D DESC RIP T IO N

ErrorInfo.Create(String [, Boolean] [, var Record] [, Integer] [, Creates a new ErrorInfo object.


Integer] [, String] [, Verbosity] [, DataClassification] [,
Dictionary of [Text, Text]])

ErrorInfo.Callstack() Specifies a callstack where the ErrorInfo was collected.

ErrorInfo.Collectible([Boolean]) Specifies whether the error is collectible using


ErrorBehavior.Collect.

ErrorInfo.CustomDimensions([Dictionary of [Text, Text]]) Set of dimensions, specified as a dictionary that relates to


the error.

ErrorInfo.FieldNo([Integer]) Specifies the field ID that the error relates to.

ErrorInfo.PageNo([Integer]) Specifies the page number that the error relates to.

ErrorInfo.RecordId([RecordId]) Specifies the record ID of the record that the error relates to.

ErrorInfo.SystemId([Guid]) Specifies the system ID of the record that the error relates
to.

ErrorInfo.TableId([Integer]) Specifies the table ID that the error relates to.

Collected errors
The following methods are available on the System data type for handling collected errors. These methods can
be invoked using property access syntax.
M ET H O D DESC RIP T IO N

System.HasCollectedErrors() Gets a value indicating whether errors have been collected in


the current error collection scope.

System.GetCollectedErrors([Boolean]) Gets all collected errors in the current collection scope.

System.ClearCollectedErrors() Clears all collected errors from the current collection scope.

IMPORTANT
If you clear the list of collected errors, any changes performed in the database won't be rolled back. So, in most cases, it
makes sense to combine the clear operation with an if Codeunit.Run then … statement, as shown in the
PostWithErrorCollectCustomUI procedure of the example.

Error behavior
The ErrorBehavior specifies the behavior of collectable errors inside the method scope. Adding
[ErrorBehavior(ErrorBehavior.Collect)] to a procedure makes it possible to collect and handle errors that are
raised in the scope of the procedure.

Example
The following code example illustrates how to use collectable errors. It's built around the DoPost codeunit,
which sets simple criteria on what can or can't be included in table fields. By itself, this procedure will stop when
errors occur. By applying the ErrorBehavior(ErrorBehavior::Collect) attribute, the PostWithErrorCollect () and
PostWithErrorCollectCustomUI () procedures show you a couple ways to collect and present these errors.

pageextension 50100 CollectingErrorsExt extends "Customer List"


{
actions
{
addfirst(processing)
{
// This action doesn't collect errors. Any procedure will stop on the first error that occurs,
// and return the error.
action(Post)
{
ApplicationArea = All;
trigger OnAction()
var
i: Record Integer;
begin
i.Number := -9;
Codeunit.Run(Codeunit::DoPost, i);
end;
}

// This action collects errors. The PostWithErrorCollect procedure continues on errors,


// and displays the errors in a dialog to the user done.
action(PostWithErrorCollect)
{
ApplicationArea = All;
trigger OnAction()
begin
PostWithErrorCollect();
end;
}

// This action collects errors. The PostWithErrorCollectCustomUI procedure continues on errors,


// and displays error details in a list page when done.
// and displays error details in a list page when done.
// This implementation illustrates how you could design your own UI for displaying and
// troubleshooting errors.
action(PostWithErrorCollectCustomUI)
{
ApplicationArea = All;
trigger OnAction()
begin
PostWithErrorCollectCustomUI();
end;
}
}
}

[ErrorBehavior(ErrorBehavior::Collect)]
procedure PostWithErrorCollect()
var
i: Record Integer;
begin
i.Number := -9;
Codeunit.Run(Codeunit::DoPost, i);
// After executing the codeunit, there will be collected errors,
// and therefore an error dialog will be shown when exiting this procedure.
end;

[ErrorBehavior(ErrorBehavior::Collect)]
procedure PostWithErrorCollectCustomUI()
var
errors: Record "Error Message" temporary;
error: ErrorInfo;
i: Record Integer;
begin
i.Number := -9;
// By using Codeunit.Run, you ensure any changes to the database within
// Codeunit::DoPost are rolled back in case of errors.
if not Codeunit.Run(Codeunit::DoPost, i) then begin
// If Codeunit.Run fails, a non-collectible error was encountered,
// add this to the list of errors.
errors.ID := errors.ID + 1;
errors.Description := GetLastErrorText();
errors.Insert();
end;

// If there are collected errors, iterate through each of them and


// add them to "Error Message" record.
if HasCollectedErrors then
foreach error in system.GetCollectedErrors() do begin
errors.ID := errors.ID + 1;
errors.Description := error.Message;
errors.Validate("Record ID", error.RecordId);
errors.Insert();
end;

// Clearing the collected errors will ensure the built-in error dialog
// will not show, but instead show our own custom "Error Messages" page.
ClearCollectedErrors();

page.RunModal(page::"Error Messages", errors);


end;
}

codeunit 50100 DoPost


{
TableNo = Integer;

trigger OnRun()
begin
if Number mod 2 <> 0 then
Error(ErrorInfo.Create('Number should be equal', true, Rec, Rec.FieldNo(Number)));

if Number <= 0 then


Error(ErrorInfo.Create('Number should be larger than 0', true, Rec, Rec.FieldNo(Number)));

if Number mod 3 = 0 then


Error(ErrorInfo.Create('Number should not be divisible by 10', true, Rec, Rec.FieldNo(Number)));

// Everything was valid, do the actual posting.


end;
}

See Also
AL Simple Statements
Dialog.Error(Text [, Any,...]) Method
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 1.0.

Displays an error message and ends the execution of AL code.

Syntax
Dialog.Error(Message: Text [, Value: Any,...])

NOTE
This method can be invoked without specifying the data type name.

Parameters
Message
 Type: Text
This string contains the text of the error message you want to display to the user. Use percent signs (%) or
number signs (#) to insert variable values into the string. Place the percent or number signs where you want to
substitute the variable value. The string can be a text constant that is enabled for multilanguage functionality.
[Optional] Value
 Type: Any
Any variable or expression to be inserted in String. You can insert up to 10 values. For '#'-type fields, the value is
truncated according to the total number of number-sign characters in String. For '%'-type fields, the full length
of the value is printed.

Remarks
The window is automatically sized to hold the longest line of text and total number of lines. By calling the
method with an empty string the execution of AL code ends without displaying a message.

Programming Guidelines
We recommend the following guidelines for error messages:
Describe what is wrong and how to solve the problem.
Write a short descriptive message. Do not use more words than necessary.
Always end the error message with a period.
Use a text constant for the text of the message.
For more information, see Progress Windows, Message, Error, and Confirm Methods.

Example
This example shows how to use the Error method.

var
AccountNo: Integer;
Text000: Label 'Finance Account #1#### must not be blocked.';
Text001: Label 'Placeholder message.';
begin
AccountNo := 1230;
// The execution stops when the error statement is executed
// and all following statements will never be executed.
Error(Text000, AccountNo);
Message(Text001); // This line is not executed.
end;

The error window displays the following:


Finance Account 1230 must not be blocked.
The Error method causes execution of AL code to stop. Message Method is never executed.

See Also
Dialog Data Type
Get Started with AL
Developing Extensions
Analyzing Error Method Telemetry
Dialog.Error(ErrorInfo) Method
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 3.0.

Displays an error message and ends the execution of AL code.

NOTE
From runtime version 8.0 and onward, this method is supported in Business Central online.

Syntax
Dialog.Error(Message: ErrorInfo)

NOTE
This method can be invoked without specifying the data type name.

Parameters
Message
 Type: ErrorInfo
The ErrorInfo structure that contains error message, error type, verbosity, and data classification.

Remarks
The window is automatically sized to hold the longest line of text and total number of lines.

Programming Guidelines
We recommend the following guidelines for error messages:
Describe what is wrong and how to solve the problem.
Write a short descriptive message. Do not use more words than necessary.
Always end the error message with a period.
Use a text constant for the text of the message.
For more information, see Progress Windows, Message, Error, and Confirm Methods.

Example
This example shows how to use the Error method.
procedure InitializeFromCurrentApp()
var
InitializeErrorInfo: ErrorInfo;
begin
// Initialize the .NET object
if InitializeFromCurrentAppInternal() then
IsInitialized := true
else begin
InitializeErrorInfo.DataClassification := DataClassification::SystemMetadata;
InitializeErrorInfo.ErrorType := ErrorType::Client;
InitializeErrorInfo.Verbosity := Verbosity::Error;
InitializeErrorInfo.Message := CannotInitializeErr;
Error(InitializeErrorInfo);
end;
end;

The error window displays the following:


Finance Account 1230 must not be blocked.
The Error method causes execution of AL code to stop. Message Method is never executed.

See Also
Dialog Data Type
Get Started with AL
Developing Extensions
Analyzing Error Method Telemetry
Dialog.LogInternalError(Text, DataClassification,
Verbosity) Method
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 6.0.

Log internal errors for telemetry.

NOTE
This method is supported only in Business Central on-premises.

Syntax
Dialog.LogInternalError(Message: Text, DataClassificationInstance: DataClassification, VerbosityInstance:
Verbosity)

NOTE
This method can be invoked without specifying the data type name.

Parameters
Message
 Type: Text
This string contains the text of the error message you want to log into telemetry. It is not what the user will get,
they will only get a generic error message.
DataClassificationInstance
 Type: DataClassification
Sets the classification of the data in the error message.
VerbosityInstance
 Type: Verbosity
Represents the security level of events.

See Also
Dialog Data Type
Get Started with AL
Developing Extensions
Dialog.LogInternalError(Text, Text,
DataClassification, Verbosity) Method
2/6/2023 • 2 minutes to read • Edit Online

Version : Available or changed with runtime version 6.0.

Log internal errors for telemetry.

NOTE
This method is supported only in Business Central on-premises.

Syntax
Dialog.LogInternalError(Message: Text, SubstitutionString: Text, DataClassificationInstance:
DataClassification, VerbosityInstance: Verbosity)

NOTE
This method can be invoked without specifying the data type name.

Parameters
Message
 Type: Text
This string contains the text of the error message you want to log into telemetry. Use a percent sign (%) to insert
a variable value into the string. Place the percent where you want the system to substitute the variable value.
You may only insert one variable value. It is not what the user will get, they will only get a generic error
message.
SubstitutionString
 Type: Text
This string replaces a percent sign in the "Message" Parameter.
DataClassificationInstance
 Type: DataClassification
Sets the classification of the data in the error message.
VerbosityInstance
 Type: Verbosity
Represents the security level of events.

See Also
Dialog Data Type
Get Started with AL
Developing Extensions
Formatting Decimal Values in Fields
2/6/2023 • 5 minutes to read • Edit Online

This article describes how you can format the decimal values that appear in fields on table, pages and reports.
For example, you can change how the data appears in a Cue on the Role Center page. To format data, you use a
combination of the AutoFormatType Property, AutoFormatExpression Property, and DecimalPlaces Property of
the field. These properties work together to enable you to specify the following:
Display amounts and unit amounts in another currency.
Specify the number of decimal places.
Specify whether to display a thousand separator.
Specify characters before and after the value, such as currency signs or %.

Implementation overview
When a field is used on a page or report, you can set the AutoFormatType and AutoFormatExpr properties
directly on the page field or report field (column), or you can set them on the underlying table field. If you
specify the properties on the table field, then the format applies wherever the field is used. Specifying the
properties on the page or report field will only apply the format to the specific page or report. If you specify the
properties on the table field and the page or report field, then the settings on the page or report field take
precedence.
When you use the AutoFormatType and AutoFormatExpression properties to format a field, two events are
raised by the system codeunit 45 Auto Format : OnResolveAutoFormat and OnAfterResolveAutoFormat.

Setting up data formatting


The settings for the AutoFormatType , AutoFormatExpression , and DecimalPlaces properties will depend
on the type of data that is displayed, for example, this could be currency amounts, unit amounts, simple
decimals, or ratios. For the most part, the AutoFormatType property is the primary setting, which in turn
determines the options for setting the DecimalPlaces and AutoFormatExpr properties.
If the AutoFormatType is not set or is set to an incorrect property value, then the default setting is used,
regardless of whether the AutoFormatExpression or DecimalValues properties are set. The default setting
uses AutoFormatType = 1 and AutoFormatExpression = '' .
The following tables describes how to set each of the properties to achieve the format that you want.

Setting the DecimalPlaces property


With the following set up, the AutoFormatExpression property is ignored.

A UTO F O RM AT T Y P E P RO P ERT Y DEC IM A L P L A C ES P RO P ERT Y USA GE DESC RIP T IO N


A UTO F O RM AT T Y P E P RO P ERT Y DEC IM A L P L A C ES P RO P ERT Y USA GE DESC RIP T IO N

0 Set to the number of decimal places Use this configuration when you want
that you want to display for the value. to format the decimal value according
the Standard Format 0 (which is the
default format) with a specific number
of decimal places.

For example, if the value is a US


decimal -76543.21 and you set the
DecimalPlaces property to 0 , then
the value appears as 76,543 . The
properties will look like this:

AutoFormatType = 0;
DecimalPlaces = 0;

Setting the AutoFormatExpression property


With the following setup, the DecimalPlaces property is ignored.

A UTO F O RM AT T Y P E P RO P ERT Y A UTO F O RM AT EXP RESSIO N P RO P ERT Y USA GE DESC RIP T IO N

1 Set to return a currency code, such as Use this configuration when you want
USD or IDR. The blank currency code to format the data as an amount. For
'' denotes LCY and is the default example, a sales order will use two
value. decimals when the currency is defined
as US dollar and no decimals when the
currency is defined as IDR (Indonesian
rupiah). For example:

AutoFormatType = 1;
AutoFormatExpression = 'IDR';

2 Set to return a currency code such as This is similar to the previous


USD or IDR. The blank currency code configuration where the
'' denotes LCY and is the default AutoFormatType property is set to
value. 1 , except you use this configuration
when you want to format the data as a
unit amount.
A UTO F O RM AT T Y P E P RO P ERT Y A UTO F O RM AT EXP RESSIO N P RO P ERT Y USA GE DESC RIP T IO N

10 Set to the property according to the Use SubType 1 to add the currency
following syntax: symbol and use the amount type
precision. You use SubType 2 for unit
'[SubType][,<currencycode or amount precision. For example, set the
expression>[,<PrefixedText>]]'
property to '1,USD' to add the $
symbol, like $543.21 .
SubType can be 1 , 2 , another
number, or omitted: AutoFormatType = 10;
AutoFormatExpression = '1,USD';
1 sets the value to an amount type
(see 1 above). 2 sets the value to a If you omit the SubType, you can use
unit amount type (see 2 above). The this configuration to customize the
syntax for these two settings is: format based on one of the standard
formats. This option enables you to
'SubType,<currencycode[,
<PrefixedText>]'
specify characters before and after the
decimal value, such as currency signs $
and percent %.
If you omit the subtype or use a
number other than 1 or 2, the syntax
For example, if you want to prefix the
is:
decimal value with a $ , include a
thousand separator, and have a
'<CustomNumber>, <expression>[,
<PrefixedText>]' maximum of two decimal places, such
as $76,453.21 , then you can set the
where <expression> sets the properties to:
precision and one of the standard
AutoFormatType = 10;
formats. For more information, see
Standard Formats. AutoFormatExpression =
'$<precision, 2:2><standard
format, 0>'

If you want to display the decimal


value as a percentage, then you can
add % at the end of the setting. For
example:

AutoFormatType = 10;
AutoFormatExpression =
'<precision, 1:1><standard
format,0>%'

When you include a % at the end of


the setting, then the decimal value is
assumed to be the ratio, and the
decimal value will be multiplied by 100.
For example, a value of 0.98 will be
formatted to 98%.

11 Set the property to the standard Use this option when you want full
format as explained below. For control over the formatting. The
example: format string will be applied exactly as
specified in the AutoFormatExpr
'<Precision,3:3><Standard property.
Format,0>'

Precision
The precision determines the minimum and maximum number of decimal points for values. The precision takes
the format <precision,minimum:maximum> . For example, <precision,minimum:maximum> sets the data with a
minimum of 2 and a maximum of 3 decimal places.
Standard formats
The following table describes the standard formats that are available for the AutoFormatExpr property when
the AutoFormatType property is set to 10.

STA N DA RD F O RM AT F O RM AT DESC RIP T IO N EURO P E DEC IM A L EXA M P L E US DEC IM A L EXA M P L E

0 <Sign><Integer -76.543,21 -76,543.21


Thousand><Point or
Comma><Decimals>

1 <Sign><Integer><Point or -76543,21 -76543.21


Comma><Decimals>

2 <Sign><Integer><Point or -76543.21 -76543.21


Comma><Decimals>

3 <Integer Thousand><Point 76.543,21- 76,543.21-


or Comma><Decimals>
<Sign>

4 <Integer><Decimals> 76543,21- 76543.21-


<Point or Comma><Sign>

9 XML format -76543.21 -76543.21

See Also
AutoFormatType Property
AutoFormatExpression Property
DecimalPlaces Property
Formatting Values, Dates, and Time
2/6/2023 • 6 minutes to read • Edit Online

With the Format function in Business Central, you can set the format of the source expression for various data
types in AL.

Remarks
You can choose to set Format to a predefined format, or you can build your own format. For more information,
see Format Method (Integer, Text).

Basic Settings
To choose a predefined format, use the syntax: <Standard Format,X>, where X is one of the entries in the Value
column of the following table.

VA L UE DESC RIP T IO N

0 Standard Display Format (the default for all data types)

1 Standard Display Format 2 (edit)

2 AL Code Constant Format

NOTE
You must enter the < and > angle brackets, such as <Standard Format,2> .

Building Formats
You can use Format to create your own formats. To create a format, use the following rules:
A format property consists of zero or more Chars, Fields, or Attributes.
Fields and Attributes are expressed by using an identifier enclosed in brackets (<>).
Attributes must contain a comma (,) and a parameter after the identifier.
Fields can optionally take a comma (,) and a FieldLen.
The following table shows the syntax.

SY N TA X VA L UES

FormatProperty := [<Char> | <Field> | <Attribute>]

<Char> := character with ASCII value [32..255]


SY N TA X VA L UES

<Field> := '<' <FieldName> [',' <FieldLen>] '>'

[, <Attribute>]

<FieldName> := literal name of field (format component)

<FieldLen> := length of field (0 or no entry means that the length is


dynamic)

<Attribute> := ['<' <AttributeName> ',' <Char> '>']

<AttributeName> := [Standard Format | 1000Character | Comma | Overflow | Filler


Character | Precision]

The 1000Character attribute specifies the character that separates the thousandths place digit from the
hundredths place digit, the millionth place digit from the hundred thousandths place digit, and so on. The
1000Character attribute must be after the Integer or Integer Thousand field name and before the Decimals field
name.
The Comma attribute specifies the character that separates the integer from the decimals. The Comma attribute
must be after the Decimals field name.
Filler Character indicates the character that is used to fill empty spaces.
The FieldName is a component that you can use to build a format expression. Depending on the data type in the
field, you can choose the appropriate FieldName from this list.

DATA T Y P E F IEL DN A M E VA L UES

Decimal Sign, Integer, Decimals, Integer Thousand

Date Day, Month, Month Text, Quarter, Year, Year4, Week, Week
Year, Week Year4, Weekday, Weekday Text, Closing

Time Hours24, Hours12, Minutes, Seconds, Thousands, AM/PM,


Second dec

DateTime Day, Month, Month Text, Quarter, Year, Year4, Week, Week
Year, Week Year4, Weekday, Weekday Text, Hours24,
Hours12, Minutes, Seconds, Thousands, AM/PM, Second dec
Note: "Second dec" specifies a fraction of a second, in
decimal format.

Integer, BigInteger Sign, Integer, Integer Thousand

Boolean Text, Number

Option Text, Number

Code Text

Char Char/Number, Char, Number


DATA T Y P E F IEL DN A M E VA L UES

Text Text

Example
The following examples demonstrate how to use Format :
Choosing a standard format.
Use the Standard Format attribute to select one of the standard formats (these are listed at the end of this
topic).
For example, <Standard Format,5> selects Standard Format 5.
Using a standard format with an attribute.
<Precision,2:3><Standard Format,0> will use Standard Format 0 and will format the data with a
minimum of 2 and a maximum of 3 decimal places. For more information, see DecimalPlaces Property. If
you do not specify a precision, then the page uses the precision that is specified in the DecimalPlaces
Property of the corresponding field in the table.
Building a format.
You can create your own formats using Chars (which are displayed literally), Fields (to choose specific
components of a value, for example the year-part of a date) and Attributes (for example to select which
character to use as a filler).
For example, a field that is based on a source expression of the Date data type can use the following
format string:
<Weekday Text>, <Month Text> <Day>
This expression displays the date as Monday, April 15 .

NOTE
The settings that are specified under the Regional and Language Options in Windows determine how some
separators are displayed. In the Business Central client, you can specify a Region under Settings , this determines
how thousand and decimal separators are displayed.

Standard Decimal Formats


This table shows the standard Decimal formats with the regional setting of a European country/region.

EURO P E DEC IM A L F O RM AT EXA M P L E

<Sign><Integer Thousand> 0 -76.543,21


<Decimals>

<Sign><Integer><Decimals> 1 -76543,21

<Sign><Integer><Decimals> 2 -76543.21
<Comma,.>

<Integer Thousand><Decimals> 3 76.543,21-


<Sign,1>
EURO P E DEC IM A L F O RM AT EXA M P L E

<Integer><Decimals><Sign,1> 4 76543,21-

<XML format> 9 -76543.21

The following table shows the standard Decimal formats with the regional setting of English (US).

US DEC IM A L F O RM AT EXA M P L E

<Sign><Integer Thousand> 0 -76,543.21


<Decimals>

<Sign><Integer><Decimals> 1 -76543.21

<Sign><Integer><Decimals> 2 -76543.21

<Integer Thousand><Decimals> 3 76,543.21-


<Sign,1>

<Integer><Decimals><Sign,1> 4 76543.21-

<XML format> 9 -76543.21

Standard Date Formats


The following table shows the standard Date formats with the regional setting of a European country/region.

EURO P E DAT E F O RM AT EXA M P L E

<Closing><Day,2>-<Month,2>- 0 05-04-21
<Year>

<Closing><Day,2>-<Month,2>- 1 05-04-21
<Year>

<Day,2><Month,2><Year> 2 050421D
<Closing>D

<Closing><Year>-<Month,2>- 3 21-04-05
<Day,2>

<Closing><Day>. <Month Text> 4 5. April 2021


<Year4>

<Closing><Day,2><Month,2><Year> 5 050421

<Closing><Year><Month,2><Day,2> 6 210405

<Day,2><Filler Character, >. <Month 7 5. Apr 2021


Text,3> <Year4>

<XML format> 9 2021-04-05


The following table shows the standard Date formats with the regional setting of English (US).

US DAT E F O RM AT EXA M P L E

<Closing> 0 04/05/21
<Month,2>/<Day,2>/<Year>

<Closing> 1 04/05/21
<Month,2>/<Day,2>/<Year>

<Month,2><Day,2><Year> 2 040521D
<Closing>D

<Closing> 3 21/04/05
<Year>/<Month,2>/<Day,2>

<Month Text> <Closing><Day>, 4 April 5, 2021


<Year4>

<Closing><Month,2><Day,2><Year> 5 040521

<Closing><Year><Month,2><Day,2> 6 210405

<Day,2><Filler Character, >. <Month 7 5. Apr 2021


Text,3> <Year4>

<XML format> 9 2021-04-05

Standard Time Formats


The following table shows the standard Time formats with the regional setting of a European country/region.

EURO P E T IM E F O RM AT EXA M P L E

<Hours24>.<Minutes,2>. 0 4.35.55
<Seconds,2>

<Hours24>.<Minutes,2>. 1 4.35.55.553
<Seconds,2><Second dec.>

<Hours24,2><Filler Character,0> 2 043555.553T


<Minutes,2><Seconds,2> <Second
dec.><Comma,.>T

<XML format> 9 04:35:55.553

The following table shows the standard Time formats with the regional setting of English (US).

US T IM E F O RM AT EXA M P L E

<Hours12>:<Minutes,2>: 0 4:35:55 AM
<Seconds,2><Second dec.>
<AM/PM>
US T IM E F O RM AT EXA M P L E

<Hours12>:<Minutes,2>: 1 4:35:55.553 AM
<Seconds,2><Second dec.>
<AM/PM>

<Hours24,2><Filler Character,0> 2 043555 .553T


<Minutes,2><Seconds,2> <Second
dec.>T

<XML format> 9 04:35:55.553

Standard DateTime Formats


The following table shows the standard DateTime formats with the regional setting of a European
country/region.

EURO P E DAT ET IM E F O RM AT EXA M P L E

<Day,2>-<Month,2>-<Year> 0 05-04-21 04:35


<Hours24,2>.<Minutes,2>

<Day,2>-<Month,2>-<Year> 1 05-04-21 04:35:55,553


<Hours24,2>.<Minutes,2>.
<Seconds,2><Second dec>

<Day,2>-<Month,2>-<Year> 2 05-04-21 04:35


<Hours24,2>.<Minutes,2>

<Day,2>-<Month,2>-<Year> 3 05-04-21 04:35:55


<Hours24,2>.<Minutes,2>.
<Seconds,2>

<XML format> Warning: A DateTime 9 2021-04-05T03:35:55.553Z


is stored in the database as
Coordinated Universal Time (UTC). For
example, on a computer in the
(UTC+01:00) Brussels, Copenhagen,
Madrid, Paris time zone, UTC is one
hour earlier than local time on the
computer and probably two hours
earlier during summer time.

The following table shows the standard DateTime formats with the regional setting of English (US).

US DAT ET IM E F O RM AT EXA M P L E

<Month,2>/<Day,2>/<Year> 0 04/05/21 04:35 AM


<Hours12,2>:<Minutes,2>
<AM/PM>

<Month,2>/<Day,2>/<Year> 1 04/05/21 04:35:55.553 AM


<Hours12,2>:<Minutes,2>:
<Seconds,2><Second dec>
<AM/PM>
US DAT ET IM E F O RM AT EXA M P L E

<Month,2>/<Day,2>/<Year> 2 04/05/21 04:35 AM


<Hours12,2>:<Minutes,2>
<AM/PM>

<Month,2>/<Day,2>/<Year> 3 04/05/21 04:35:55 AM


<Hours12,2>:<Minutes,2>:
<Seconds,2> <AM/PM>

<XML format> Warning: A DateTime 9 2021-04-05T12:35:55.553Z


is stored in the database as
Coordinated Universal Time (UTC). For
example, on a computer in the (UTC-
08:00) Pacific Time zone, UTC is eight
hours later than local time on the
computer.

Standard Integer Formats


IN T EGER A N D B IGIN T EGER F O RM AT EXA M P L E

<Sign><Integer> 0 -567

<Sign><Integer> 1 -567

<Sign><Integer> 2 -567

<XML format> 9 -567

Standard Boolean Formats


B O O L EA N F O RM AT EXA M P L E

<Text> 0 True/False

<Text> 1 True/False

<Number> 2 1/0

<XML format> 9 true/false

Standard GUID Formats


GUID F O RM AT EXA M P L E

{<4byte>-<2byte>-<2byte>- 0 {EA48A3E0-48E0-4AB7-B1A1-
<2byte>-<6byte>} E3EA85BF1B75}

{<4byte>-<2byte>-<2byte>- 1 {EA48A3E0-48E0-4AB7-B1A1-
<2byte>-<6byte>} E3EA85BF1B75}
GUID F O RM AT EXA M P L E

{<4byte>-<2byte>-<2byte>- 2 {EA48A3E0-48E0-4AB7-B1A1-
<2byte>-<6byte>} E3EA85BF1B75}

<16byte> 3 EA48A3E048E04AB7B1A1E3EA85BF1B
75

<4byte>-<2byte>-<2byte>- 4 EA48A3E0-48E0-4AB7-B1A1-
<2byte>-<6byte> E3EA85BF1B75

(<4byte>-<2byte>-<2byte>- 5 (EA48A3E0-48E0-4AB7-B1A1-
<2byte>-<6byte>) E3EA85BF1B75)

{0X<4byte>,0X<2byte>,0X<2byte>, 6 {0XEA48A3E0,0X48E0,0X4AB7,
{0X<1byte>,0X<1byte>,0X<1byte>,0 {0XB1,0XA1,0XE3,0XEA,0X85,0XBF,0X1
X<1byte>, B,0X75}}
0X<1byte>,0X<1byte>,0X<1byte>,0X
<1byte>}}

<XML format> 9 {EA48A3E0-48E0-4AB7-B1A1-


E3EA85BF1B75}

Standard Enum Formats


EN UM VA L UE F O RM AT EXA M P L E

<Text> 0 Bronze

<Text> 1 Bronze

<Number> 2 1

<XML format> 9 1

Standard Option Formats


O P T IO N F O RM AT EXA M P L E

<Text> 0 Blue

<Text> 1 Blue

<Number> 2 1

<XML format> 9 1

Standard XML and String Formats


Standard format 9 is used to display the data in the standard XML formats.
For Chars, all formats should resemble the following: <Char/Number>.
For Text and Code, all formats should resemble the following: <Text>.

See Also
DecimalPlaces Property
About Dates in Business Central
Tables Overview
2/6/2023 • 2 minutes to read • Edit Online

Tables are the fundamental objects in any database. They are the objects in which you store and manipulate
data. This is true no matter what kind of data you need to manage. When you create a new database, you begin
by building the tables. Later, you create pages and reports in order to access and view the data in the tables.
A table can be visualized as a two-dimensional matrix, consisting of columns and rows. The following illustration
shows a table where each row is a record and each column is a field.
A table consists of two parts: the table data and a table description. The table data is the part users often think of
as comprising the database, because it contains the actual records with their data fields. The layout and
properties of those fields, however, are specified by the table description. The table description is not directly
visible to the user. The following illustration shows how the table data and the table description together form a
table.

When you design a table, you assign a number of characteristics to it, such as a name, an ID number, and the
fields it contains. You also assign a number of characteristics (such as name, ID number, data type, and initial
value) to each field. When you design a new table, you also specify which keys you want the system to maintain.
All these characteristics are stored in the table description when you save your table design.
The information in the table description is used by SQL Server and occasionally by database users who need
information about the table structure. The table description makes the database flexible, as it lets the system
access tables with different structures. The database can extract the definitions of the table structure from the
table description and thereby correctly access any table.
The following illustration shows that a table description contains properties, triggers, fields, and keys and shows
how these are related.

The table description contains some properties that are related to the table, others that are related to the fields
in the table, and other properties related to keys. You can also see that triggers are defined both for the table
and for the fields in the table.
Creating tables
In AL code, you can create new tables or modify existing tables. Read more about creating and modifying tables
in the following sections.

TO SEE

Create a new table object Table Object

Modify an existing table object Table Extension Object

Decide which field data type you want to apply to your data Field Data Types

Apply table and field properties Table and Table Extension Properties

Set primary and secondary table keys Table Keys

Using triggers in database design


Dynamics 365 Business Central supports setting up actions to take place in response to specific events. These
are known as triggers. The following topics help to explain how Dynamics 365 Business Central implements this
feature of database design.

TO SEE

Learn about the set of triggers that Dynamics 365 Business Table Triggers
Central supports for tables and fields. Table Extension Triggers
Field Triggers
Field Extension Triggers

Creating relationships between tables


In Dynamics 365 Business Central, the primary way to establish a connection between tables is to use the
TableRelation property. The following topics go into detail about how this works.

TO SEE

Get a brief introduction to relational database design in Setting Relationships Between Tables
Dynamics 365 Business Central.

See Also
Developing Extensions in AL
Tables Overview
2/6/2023 • 2 minutes to read • Edit Online

Tables are the fundamental objects in any database. They are the objects in which you store and manipulate
data. This is true no matter what kind of data you need to manage. When you create a new database, you begin
by building the tables. Later, you create pages and reports in order to access and view the data in the tables.
A table can be visualized as a two-dimensional matrix, consisting of columns and rows. The following illustration
shows a table where each row is a record and each column is a field.
A table consists of two parts: the table data and a table description. The table data is the part users often think of
as comprising the database, because it contains the actual records with their data fields. The layout and
properties of those fields, however, are specified by the table description. The table description is not directly
visible to the user. The following illustration shows how the table data and the table description together form a
table.

When you design a table, you assign a number of characteristics to it, such as a name, an ID number, and the
fields it contains. You also assign a number of characteristics (such as name, ID number, data type, and initial
value) to each field. When you design a new table, you also specify which keys you want the system to maintain.
All these characteristics are stored in the table description when you save your table design.
The information in the table description is used by SQL Server and occasionally by database users who need
information about the table structure. The table description makes the database flexible, as it lets the system
access tables with different structures. The database can extract the definitions of the table structure from the
table description and thereby correctly access any table.
The following illustration shows that a table description contains properties, triggers, fields, and keys and shows
how these are related.

The table description contains some properties that are related to the table, others that are related to the fields
in the table, and other properties related to keys. You can also see that triggers are defined both for the table
and for the fields in the table.
Creating tables
In AL code, you can create new tables or modify existing tables. Read more about creating and modifying tables
in the following sections.

TO SEE

Create a new table object Table Object

Modify an existing table object Table Extension Object

Decide which field data type you want to apply to your data Field Data Types

Apply table and field properties Table and Table Extension Properties

Set primary and secondary table keys Table Keys

Using triggers in database design


Dynamics 365 Business Central supports setting up actions to take place in response to specific events. These
are known as triggers. The following topics help to explain how Dynamics 365 Business Central implements this
feature of database design.

TO SEE

Learn about the set of triggers that Dynamics 365 Business Table Triggers
Central supports for tables and fields. Table Extension Triggers
Field Triggers
Field Extension Triggers

Creating relationships between tables


In Dynamics 365 Business Central, the primary way to establish a connection between tables is to use the
TableRelation property. The following topics go into detail about how this works.

TO SEE

Get a brief introduction to relational database design in Setting Relationships Between Tables
Dynamics 365 Business Central.

See Also
Developing Extensions in AL
Table Object
2/6/2023 • 2 minutes to read • Edit Online

Tables are the core objects used to store data in Dynamics 365 Business Central. No matter how data is
registered in the product - from a web service to a finger swipe on the phone app, the results of that transaction
will be recorded in a table.
The structure of a table has four sections:
The first block contains metadata for the overall table, such as the table type.
The fields section describes the data elements that make up the table, such as their name and the type of data
they can store.
The keys section contains the definitions of the keys that the table needs to support.
The final section details the triggers and code that can run on the table.

IMPORTANT
Only tables with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

IMPORTANT
System and virtual tables can't be extended. System tables are created in the ID range of 2.000.000.000 and above. For
more information about object ranges, see Object Ranges.

Snippet support
Typing the shortcut ttable will create the basic layout for a table object when using the AL Language extension
in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Table example
This table stores address information and it has four fields; Address , Locality , Town/City , and County .
table 50104 Address
{
Caption = 'Sample table';
DataPerCompany = true;

fields
{
field(1; Address; Text[50])
{
Description = 'Address retrieved by Service';
}
field(2; Locality; Text[30])
{
Description = 'Locality retrieved by Service';
}
field(3; "Town/City"; Text[30])
{
Description = 'Town/City retrieved by Service';
}
field(4; County; Text[30])
{
Description = 'County retrieved by Service';

trigger OnValidate();
begin
ValidateCounty(County);
end;

}
}
keys
{
key(PrimaryKey; Address)
{
Clustered = TRUE;
}
}

var
Msg: Label 'Hello from my method';

trigger OnInsert();
begin

end;

procedure MyMethod();
begin
Message(Msg);
end;
}

System fields
The Dynamics 365 Business Central platform will automatically add several system fields to tables. For more
information, see System Fields.

See Also
AL Development Environment
Table Overview
Table Extension Object
SqlTimestamp Property
Table Keys
Table, Table Fields, and Table Extension Properties
System Fields
2/6/2023 • 6 minutes to read • Edit Online

System fields are fields that are automatically included in every table object by the platform. Dynamics 365
Business Central includes the following system fields:
SystemId
Data audit fields
Timestamp
System fields are assigned numbers in the range 2000000000-2147483647. This range is reserved for system
fields. You'll get a design-time error if you give a field a number in this range.

SystemId field
APPLIES TO: Business Central 2019 release wave 2 and later

The SystemId field is a GUID data type field that specifies a unique, immutable (read-only) identifier for records
in the table. The SystemId field has the following characteristics and behavior:
All records must have a value in the SystemId field.
You can assign your own value when a record is inserted in the database. Otherwise, the platform will
automatically generate and assign a value.
Once the SystemId has been set, it can't be changed.
There's always a unique secondary key on the SystemId field to ensure records don't have identical field
values.
The SystemId field is given the field number 2000000000.
The SystemId field is exposed in the platform code and for AL code, allowing you to code against it. For
example:
The Insert(Boolean, Boolean) lets you specify the SystemId value for a record, instead of using one
assigned by the platform:

myRec.SystemId := '{B6666666-F5A2-E911-8180-001DD8B7338E}';
myRec.Insert(true, true);

The GetBySystemId(Guid) uses the SystemId to get a record:

id := myRec.GetBySystemId('{B6666666-F5A2-E911-8180-001DD8B7338E}';

The SystemIdNo() gets the field number used by the SystemId field in the table:

myRec.Open(DATABASE::MyTable);
SystemIdFieldNo := myRec.SystemIdNo();

The TableRelation lets you use the SystemId field to set up table relationships:
field(1; MyField; Guid)
{
DataClassification = ToBeClassified;
TableRelation = Customer.SystemId;
}

The SystemId field can be used as a binding key to an API:

page 50100 "Customer Entity"


{
PageType = API;
ApplicationArea = All;
UsageCategory = Administration;
SourceTable = Customer;
ODataKeyFields = SystemId;
...

APPLIES TO: Business Central 2020 release wave 2 and later

If the SystemId field is specified in a Web Service POST request, the OData stack persists the value in the
database.
The SystemId field can be used as part of a (non-primary) key.
You can show the SystemId field as a field on a page.
You can link FactBoxes/page parts using the SystemId field.

Data audit fields


APPLIES TO: Business Central 2020 release wave 2 and later

Every table in Business Central includes the following four system fields, which can be used for auditing records:

C O L UM N N A M E ( IN
F IEL D N A M E ( IN A L ) DATA B A SE) DATA T Y P E F IEL D N UM B ER DESC RIP T IO N

SystemCreatedAt $systemCreatedAt DateTime 2000000001 Specifies the data


and time that the
record was created.

SystemCreatedBy $systemCreatedBy GUID 2000000002 Specifies security ID


(SID) of the user that
created the record.

SystemModifiedAt $systemModifiedAt DateTime 2000000003 Specifies the data


and time that the
record was last
modified.

SystemModifiedBy $systemModifiedBy GUID 2000000004 Specifies the SID of


the user that last
modified the record

Runtime characteristics
At runtime, the data audit fields have the following characteristics and behavior:
The platform will automatically generate and assign values according to the following triggers:
After all OnBeforeInsert and OnBeforeModify triggers are run
After the OnInsert and OnModify triggers are run
Before all OnAfterInsert and OnAfterModify triggers are run

NOTE
You can assign the values, but the values written to the database are always provided by the platform.

Fields are populated as follows:


When a new record is created, before calling Insert, the audit fields are given blank GUIDs and blank
dates as values.
When a record is first inserted, the fields are populated with actual values.
The $systemCreatedBy and $systemModifiedBy fields are given the same value. So are the
$systemCreatedAt and $systemModifiedAt fields.
The $systemCreatedBy and $systemCreatedAt fields won't change after this point.
When a record is updated, the $systemModifiedBy and $systemModifiedAt fields are changed.
The platform won't populate audit field values in these cases:
Copying company. The values in the tables of the company being copied stay the same, and the values are
copied to the tables of the new company.
Synchronizing the table schema with the application.

NOTE
Audit fields can't be imported with configuration packages.

In AL
The data audit fields are exposed in AL code. As a developer, the audit fields give you an easy and performant
way to program against historical data. For example, you can write AL queries that return data changes since a
specific date and time.
The following methods are available on the RecordRef data type:

M ET H O D DESC RIP T IO N

SystemCreatedAtNo Gets the field number that is used by the


SystemCreatedAt field.

SystemCreatedByNo Gets the field number that is used by the


SystemCreatedBy field.

SystemModifiedAtNo Gets the field number that is used by the


SystemModifiedAt field.

SystemModifiedByNo Gets the field number that is used by the


SystemModifiedBy field.

There are a couple points of interest you should know:


If a record is copied into a temporary table, the data audit field values are copied as well. The values aren't
changed by the server when calling a modify or insert method.
It's possible to use audit fields in a key. The platform doesn't automatically index these fields in any way.
If you want to translate a user security ID GUID to the corresponding user name, the following AL code might be
useful:

procedure GetUserNameFromSecurityId(UserSecurityID: Guid): Code[50]


var
User: Record User;
begin
User.Get(UserSecurityID);
exit(User."User Name");
end;

Timestamp field
The timestamp field contains rowversion numbers for records, as maintained in SQL Server. In SQL server,
timestamp is a synonym for the rowversion data type. The value of the timestamp field is an automatically
generated, unique binary number. The timestamp is a mechanism for version-stamping table rows.
A typical use of the timestamp field is for synchronizing data changes in tables. It lets you identify records that
have changed since the last synchronization. For example, you can read all the records in a table, then store the
highest timestamp value. Later, you can query and retrieve records that have a higher timestamp value than
the stored value.
In AL
In AL code, the timestamp is accessible through the SystemRowVersion field. However, you can't write to the
field.
The following methods are also available on the Database data type:

M ET H O D DESC RIP T IO N

LastUsedRowVersion Gets the last used rowversion from the database. This
method does the same as the @@DBTS (Transact-SQL)
function.

MinimumActiveRowVersion Gets the lowest active rowversion in the database. This


method returns the lowest rowversion of any uncommitted
rows. Rows that have a lower timestamp than this returned
value are guaranteed to be committed. If there are no active
transactions, the value is equal to LastUsedRowVersion + 1.
This method does the same as the
MIN_ACTIVE_ROWVERSION (Transact-SQL) function.

Expose the timestamp field in Business Central version 20 and earlier


In versions of Business Central earlier than version 21, the timestamp field is hidden. But, you can expose it by
using SqlTimestamp Property. You're then able to write code against it, add filters, and so on, similar to any
other field in a table.
1. Add a field that has the data type BigInteger .
Specify a name for the field, such as Record Time Stamp . You can specify any valid name for field, but you
can't use timestamp because it's a reserved name.
2. Set the SqlTimestamp property to true .
For example:
field(3; "Record Time Stamp"; BigInteger)
{
SqlTimestamp = true;
}

Alternatively, you can use a FieldRef Data Type variable to access the timestamp value of a record, as follows:
1. Create a RecordRef Data Type variable that references the record in a table for which you want to retrieve
its timestamp.
2. Use the Field Method on the RecordRef variable to get the FieldRef for the field that has the number 0.
This field contains the timestamp value.
The following example shows how to retrieve the timestamp value for the first record in the Customer table.
RecordRef and FieldRef are RecordRef Data Type and FieldRef Data Type variables, respectively.

RecordRef.Open(DATABASE::Customer);
RecordRef.FindFirst();
FieldRef := RecordRef.Field(0);
Message(Format(FieldRef.Value()));

See Also
Table Object
AL Development Environment
Table Overview
Table Extension Object
SqlTimestamp Property
Table Keys
Table Properties
Table Extension Object
2/6/2023 • 2 minutes to read • Edit Online

The table extension object allows you to add additional fields or to change some properties on a table provided
by the Dynamics 365 Business Central service. In this way, you can add data to the same table and treat it as a
single table. For example, you may want to create a table extension for a retail winter sports store. In your
solution you want to have ShoeSize as an additional field on the customer table. Adding this as an extension
allows you to write code for the customer record and also include values for the ShoeSize .
Along with defining other fields, the table extension is where you write trigger code for your additional fields.
When developing a solution for Dynamics 365 Business Central , you will follow the code layout for a table
extension as shown in the example below.

IMPORTANT
Only tables with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

IMPORTANT
System and virtual tables cannot be extended. System tables are created in the ID range of 2.000.000.000 and above. For
more information about object ranges, see Object Ranges.

IMPORTANT
Extending tables from Dynamics 365 for Sales is currently not supported.

Using a table extension to add a key to the base table


Just like in the table object, you can define keys for fields added in the table extension. But you can also add keys
for fields that only exist on the table you extend, in case you want to extend the keys provided in the base table
definition. See Table Keys for examples on how to define keys in a table extension.

Snippet support
Typing the shortcut ttableext will create the basic layout for a table extension object when using the AL
Language extension in Visual Studio Code.

Properties
Using a table extension allows you to overwrite some properties on fields in the base table. For a list of Table
properties, see Table and Table Extension Properties.
Table extension syntax
tableextension Id MyExtension extends MyTargetTable
{
fields
{
// Add changes to table fields here
}

var
myInt: Integer;
}

Table extension example


This table extension object extends the Customer table object by adding a field ShoeSize , with ID 50116 and the
data type Integer . It also contains a procedure to check if the ShoeSize field is filled in.

tableextension 50115 RetailWinterSportsStore extends Customer


{
fields
{
field(50116;ShoeSize;Integer)
{
trigger OnValidate();
begin
if (rec.ShoeSize < 0) then
begin
message('Shoe size not valid: %1', rec.ShoeSize);
end;
end;
}
}

procedure HasShoeSize() : Boolean;


begin
exit(ShoeSize <> 0);
end;

trigger OnBeforeInsert();
begin
if not HasShoeSize then
ShoeSize := Random(42);
end;
}

See Also
AL Development Environment
Table Overview
Table Object
Table, Table Fields, and Table Extension Properties
Table Keys
Setting Relationships Between Tables
2/6/2023 • 2 minutes to read • Edit Online

It is common to distinguish among the following types of relationships between tables in relational database
design:
One-to-many relationships
Many-to-many relationships
One-to-one relationships
The one-to-many relationship is the most common. If your database design model indicates that you need to set
up a many-to-many relationship, then your design is probably inefficient. You can typically break down a many-
to-many relationship into two one-to-many relationships. A one-to-one relationship is usually not optimal and
can often be avoided by combining the two tables.

Using relationships
If your database contains tables with related data, then you can define a relationship between them. You relate
tables by specifying one or more fields that contain the same value in related records. These matching fields
often have the same name in each table. You can use relationships to:
Validate data entries
Perform lookup functions in other tables
Propagate changes automatically from one table to other tables

Table relationships and the TableRelation property


Table relationships are defined in the AL Language development environment using the TableRelation
property. This property allows you to define both simple and advanced table relations.

NOTE
You can define a relationship only to a field that is a member of the primary key group.

Advanced table relations are typically prefixed with a conditional statement and include filters. The following
syntax is for table relations.

<TableRelation> =
<TableName>[.<FieldName>] [WHERE(<TableFilters>)] |
if (<Conditions>) <TableName>[.<FieldName>]
[WHERE(<TableFilters>)] else <TableRelation>
<Conditions> ::=
<TableFilters>
<TableFilters> ::=
[<TableFilter> {,<TableFilter>}]
<TableFilter> ::=
<DstFieldName>=CONST(<FieldConst>) |
<DstFieldName>=FILTER(<Filter>)

For example:
table 50120 TableWithRelation
{
fields
{
field(1; Id; Integer) { }
field(2; Type; enum TypeEnum) { }
field(3; Relation; Code[20])
{
TableRelation =
if (Type = const (Customer)) Customer
else if (Type = const (Item)) Item;
}
}
}

The following table describes each of the symbols.

SY M B O L DESC RIP T IO N

TableName Specifies the related table.

FieldName Specifies a field in the related table.

Conditions Table relations can be conditional.

TableFilters A list of table filters.

TableFilter A constant expression or a filter expression.

DstFieldName Specifies the destination field name.

Filter A filter expression, such as 10|20..30.

Examples of table relationships


For example, you have an Orders table that stores orders and a Salesperson table that stores the names of all
salespeople in your company. In the Orders table, you can include a Salesperson field that identifies the
salesperson. By setting up a relationship between these two tables, you can check whether the Salesperson
field in the Orders table contains a valid code.

For example, you have a Vendors table with all your vendors and a Currency Code table. You can create a
relationship between a Currency Code field in the Vendors table and the Currency Code table. This will
allow users to look up information about valid currency codes.
Furthermore, if you change one of the currency codes in the Currency Code table, then the change is
automatically propagated to all tables that refer to this code.

See Also
Overview of Tables
Classifying Data in Dynamics 365
2/6/2023 • 5 minutes to read • Edit Online

Dynamics 365 includes development features for tagging business data with specific classifications. Specifically,
this includes data that is stored in table fields of the database and telemetry data that is emitted from the
application.

About Data Classification


Classifying data serves different purposes. It can make data easier and more efficient to locate and retrieve, and
also help to add another layer of protection and security for handling private and sensitive data. It can
supplement your process for making the application compliant with legislative and regulatory requirements for
collecting, storing, and using personal information.

IMPORTANT
You should consider the data classification features offered in Dynamics 365 as the first layer of classification - done by
developers (Dynamics 365 and partners) on customizations, add-ons, and extensions. The second layer is to classify the
sensitivity of the data itself. For more information, see Classifying Data Sensitivity. It is also important to consider end-
users, and how they handle data they provide and that is made available to them.

What are the different data classifications?


The following table describes the different classifications that you can apply to data:

DATA C L A SSIF IC AT IO N DESC RIP T IO N EXA M P L E

CustomerContent Content directly provided/created by Customer generated BLOB or


admins and users. structured storage data
Customer-owned/provided
secrets (passwords, certificates,
encryption keys, storage keys)

EndUserIdentifiableInformation (EUII) Data that identifies or could be User name or display name
used to identify the user of a Microsoft (DOMAIN\UserName)
service. EUII does not contain User principle name
Customer content. (name@company.com)
User-specific IP address

AccountData Customer billing information and Tenant administrator contact


payment instrument information, information (for example,
including administrator contact tenant administrator’s name,
information, such as tenant address, e-mail address, phone
administrator’s name, address, or number)
phone number. Customer’s provisioning
information
DATA C L A SSIF IC AT IO N DESC RIP T IO N EXA M P L E

EndUserPseudonymousIdentifiers (EUPI) An identifier created by User GUIDs, PUIDs, or SIDs


Microsoft tied to the user of a Session IDs
Microsoft service. When EUPI is
combined with other information, such
as a mapping table, it identifies the
end user. EUPI does not contain
information uploaded or created by
the customer (Customer content or
EUII)

OrganizationIdentifiableInformation (OII) Data that can be used to identify Tenant ID (non-GUID)


a tenant, generally config or usage Domain name in e-mail address
data. This data is not linkable to a user (xxx@contoso.com) or other
and does not contain Customer tenant-specific domain
content. information

SystemMetadata Data generated while running the Database table names,


service or program that is not linkable database column names, entity
to a user or tenant. names

Classifying data in tables and fields


Table objects and field controls include the DataClassification property that you can use to tag data with one
of the classifications previously described.
Dynamics 365 operates with some standard rules for classification:
When you add a new field to a table, the field is assigned an initial value of ToBeClassified .
FlowField and FlowFilter fields are automatically set to the SystemMetadata data classification. This cannot
be changed.
Existing tables and fields (except for FlowFields and FlowFilters) in an application that has been upgraded
from a Dynamics 365 version without the DataClassification property, will automatically be assigned the
CustomerContent classification.

IMPORTANT
Microsoft is providing this DataClassification property as a matter of convenience only. It is your responsibility to
classify the data appropriately and comply with any laws and regulations that are applicable to you. Microsoft disclaims all
responsibility towards any claims related to your classification of the data.

For more information about this property, see DataClassification Property.


Data classification on upgrade
When you upgrade an application from a Dynamics 365 version that does not contain the DataClassification
property, existing tables and fields (except for FlowFields and FlowFilters) will automatically be assigned the
CustomerContent classification. You can then access the DataClassification property on these tables and
fields, and change the classification as needed. FlowFields and FlowFilters will be assigned the
SystemMetadata classification automatically.
IMPORTANT
After upgrade or import of objects, using fob files, that introduce new tables and/or fields, make sure to synchronize new
tables and/or fields to enable Data Sensitivity Classification by running SyncAllFields method in
Data Classification Mgt. Codeunit (Codeunit 1750). No action is needed when extensions are installed, as installation
of extension automatically triggers SyncAllFields method. See example below.

Run the script below from Developer Shell:

Invoke-NAVCodeunit -Tenant <TenantID> -CompanyName <CompanyName> -CodeunitID 1750 -MethodNAme


'SyncAllFields' -ServerIntance <ServerInstance>

Bulk-classifying data
The Field Data Classification report, which is described in the Viewing current field classifications section in this
topic, provides an overview of the data classifications for fields. The report also lets you assign data
classifications for more than one field. For example, this is useful if you are assigning classifications for the first
time, or have changed several fields and want to update their classifications. You can bulk-edit classifications
only for fields in AL Language development environment. The script does not update fields in extensions.
To bulk-edit classifications, export the report to Excel, update the classifications, and then save your changes.
Then, in Windows PowerShell, run the following commands to run the Import-Module script and set the
classifications on the fields.
To run the script from the default folder on the DVD, run:

Import-Module WindowsPowerShellScripts\DataClassification\DataClassification.psm1

To update the DataClassification property, run the following command. Replace <FilePath> with the full path
to the client files. For example, C:\Program Files\Microsoft Dynamics 365 Business Central\160\RoleTailored
Client.

Set-FieldDataClassificationFromExcelFile -ExcelFilePath "C:\BC\W1 Fields (Main).xlsx" -SheetName 'Field Data


Classification' -RTCFolder "<FilePath>" -DBName BC2 -OutputFolder C:\BC2\Classifications

Viewing current field classifications


To view the data classification on all fields, you can do one of the following:
From the client, search for and open the Data Classification Worksheet page.
Create a page that has the virtual table Field (ID 2000000041) as its source, and open the page in the client.

Classifying data in custom telemetry trace events


Custom telemetry trace events are defined by calls to the SENDTRACETAG method in the application code. The
SENDTRACETAG method includes an optional parameter called DataClassification that you can use to tag the
telemetry trace event with a data classification.
For more information, see SendTraceTag and Instrumenting an Application for Telemetry.

See Also
Data Classification
Classifying Data Sensitivity
Insert, Modify, ModifyAll, Delete, and DeleteAll
Methods
2/6/2023 • 4 minutes to read • Edit Online

The following methods maintain the database by adding, modifying, and removing records:
Insert
Modify
ModifyAll
Delete
DeleteAll
These methods are some of the most frequently used AL methods.
Some of these methods return an optional Boolean value that indicates whether the method succeeded. If you
do not handle the return value in your code, a run-time error occurs when a method returns false . If you handle
the return value by testing its value in an if statement, no error will occur, and you must take corrective action in
the code.

Insert method
The Insert method inserts a record in a table. Insert has the following syntax.

[Ok := ] Record.Insert([RunTrigger: Boolean[, InsertWithSystemId: Boolean]])

A record must be assigned a SystemId . You have the option to assign your own value or have the platform
assign an auto-generated value. The following example inserts a new record, with the SystemId , No., and
Name fields specified in the assigned values, while other fields will have their default values. If the No. field is
the primary key of the Customer table, then the record will be inserted in the Customer table unless the table
already contains a record with the same primary key. In this case you receive an error message because the
return value is not tested.

var
Customer: Record Customer;
begin
Customer.Init;
Customer.SystemId := '{B6666666-F5A2-E911-8180-001DD8B7338E}';
Customer."No." := '4711';
Customer.Name := 'Andrew Dixon';
Customer.Insert(false, true);
end;

IMPORTANT
After the SystemId has been set on a record, it cannot be changed.

Modify method
Modify modifies a record that already exists. For more information, see Modify Method. Modify has the
following syntax.

[Ok :=] Record.Modify([RunTrigger])

Modify returns an optional Boolean value. It returns true if the record to be modified exists; otherwise, it returns
false .
The following example changes the name of customer 4711 to Richard Roe. This example requires that you
create the following variable.

VA RIA B L E DATA T Y P E SUBT Y P E

Customer Record Customer

Customer.Get('4711');
Customer.Name := 'Richard Roe';
Customer.Modify;

ModifyAll method
ModifyAll performs a bulk update of records. For more information, see ModifyAll Method.
ModifyAll has the following syntax.

Record.ModifyAll(Field, NewValue [, RunTrigger])

ModifyAll uses the current filters. This means that you can perform the update on a specified set of records in a
table. ModifyAll returns no value, nor does it cause an error if the set of records to be changed is empty.
In the following example, the SetRange statement selects the records where Salesperson Code is PS. The
ModifyAll statement changes the Salesperson Code of these records to JR. The example requires that you create
the following variable.

VA RIA B L E DATA T Y P E SUBT Y P E

Customer Record Customer

Customer.SetRange("Salesperson Code",'PS','PS');
Customer.ModifyAll("Salesperson Code",'JR');

Delete method
Delete deletes a record from the database. For more information, see Delete Method Delete has the following
syntax.

[Ok :=] Record.Delete([RunTrigger])

The record that you want to delete must be specified by using the values in the primary key fields before you
call this method. This means that Delete does take filters into consideration.
The following example shows how to use Delete to delete the record for customer number 4711. This example
requires that you create the following variable.

VA RIA B L E DATA T Y P E SUBT Y P E

Customer Record Customer

Customer."No." := '4711';
Customer.Delete;

Delete returns an optional Boolean value. It returns true if the record could be found; otherwise, it returns false .
Unless you test this value in your code, a run-time error occurs when Delete fails.
When you are developing your own applications, you should consider the following scenario:
1. Retrieve a record from the database.
2. Perform various checks to determine whether the record should be deleted.
3. If step 2 indicated that you should delete the record, then delete it.
This can cause problems in a multi-user environment. Another user can modify or delete the same record
between your performing steps 2 and 3. If the record is modified, then perhaps the new contents of the record
would have changed your decision to delete it. If it has been deleted by the other user, you can get a run-time
error if you have just verified that the record existed (in step 1). If the design of your application indicates that
you can encounter this problem, you should consider using the LockTable method. LockTable should be used
sparingly because this method degrades performance. For more information about the LockTable method, see
LockTable Method.

DeleteAll method
DeleteAll deletes all the records that are specified by the filter settings. If no filters are applied, it deletes all the
records in the table. For more information, see DeleteAll Method DeleteAll has the following syntax.

Record.DeleteAll([RunTrigger])

The following example deletes all the records from the Customer table where the Salesperson Code is PS. This
example requires that you create the following variable.

VA RIA B L E DATA T Y P E SUBT Y P E

Customer Record Customer

Customer.SetRange("Salesperson Code", 'PS', 'PS');


Customer.DeleteAll;

NOTE
When you use DeleteAll (true), a copy of the AL variable with its initial values is created. This means that when you use
DeleteAll(true) to run the OnDelete trigger, all the changes that were made to the variables in the method or codeunit
that is making the call cannot be seen in the OnDelete trigger. If you want to see the changes that you made to the
variables, you must use Delete(true) in a loop. There is no difference in performance between using DeleteAll(true) and
using Delete(true) in a loop.
See Also
AL Methods
SystemId Field
Temporary tables
2/6/2023 • 4 minutes to read • Edit Online

A temporary table is a temporary variable that holds a table. A temporary table is used as a buffer or
intermediate storage for table data.
You can use a temporary table just like you use a database table. The differences between a temporary table and
a database table are as follows:
A temporary table data isn't stored in the database. It's only held in memory until the table is closed.
The write transaction principle that applies to a database table doesn't apply to a temporary table.

Advantage of using a temporary table


The advantage of using a temporary table is that all the interaction with a temporary table occurs on Dynamics
365 Business Central. A temporary table reduces the load on both the network and the SQL database server.
When you want to do many operations on the data in a specific database table, you can load the data into a
temporary table when you modify it. Loading the data into a temporary table speeds up the process because all
the operations are done in memory on the Business Central Server.
For endpoint performance and temporary tables, see Anti-patterns (don't do this).

Creating and using a temporary table


There are three ways to implement a temporary table:
Setting the TableType property on the table object to Temporar y .
Using a temporary record variable.
Setting the SourceTableTemporary property on a page.
Whichever way you choose, you must create the table object that defines the fields, like any other table object.
The differences are explained in the following sections.

TIP
Temporary tables retain system fields, like SystemID and data audit fields. For more information, see System Fields.

Setting the TableType to Temporary


APPLIES TO: Business Central 2020 release wave 2 and later

With this implementation, a physical table isn't created in the database. In the table object, set the TableType
property to Temporary :
table 50100 MyTable
{
DataClassification = ToBeClassified;
TableType = Temporary;

fields

...
}

This implementation has the same effect as using a temporary record variable or setting the
SourceTableTemporary property on a page. But the advantage is that the table schema isn't synchronized with
the database. So it doesn't have restrictions on breaking schema changes, like removing a field, changing its
data type or length.
It will also improve the performance of BACPAC generation using the sqlpackage command-line tool, compared
to temporary tables based on temporary record variables and pages. For more information, see Performance of
BACPAC generation.
Changing the table type
You can change from Normal to Temporar y , and the other way around. When changing Normal to
Temporar y the table, you'll have to synchronize the extension with the database. This step will remove the table
from the database. So if the table contains data, you'll have to synchronize the schema using the ForceSync
mode.

NOTE
Changing the table type is considered a destructive change. So this change can only be done with Business Central on-
premises.

Using a temporary record variable


With this implementation, a physical table isn't created in the database. You create a global or local variable of
the type record and set the Temporary Property next to it. The variable that holds a temporary table is defined
just like any other global or local variable. The syntax is shown in the following example:

var
TempInvoicePostBuffer: Record "Invoice Post. Buffer" temporary;

You manipulate the temporary table variable as you would with any other database table. For example, you can
apply filters and do searches. For more information about the operations you can do, see Record Data Type.

Using a SourceTableTemporary property on page objects


Another option for temporary tables is to set the SourceTableTemporary on all pages that use the table. This
implementation will also use a physical table in the database.
page 50100 MyPage
{
PageType = Card;
ApplicationArea = All;
UsageCategory = Administration;
SourceTable = TableName;
SourceTableTemporary = true;

layout

...
}

Temporary tables on reports and XMLPorts


You can also use temporary tables for storing the data set that's returned by a report object or imported by an
XMLPort. To do so, set the UseTemporar y proper ty to true on the relevant report data item or XMLPort table
element. For more information, see UseTemporary Property (XMLports) and UseTemporary Property (Reports).
Temporary tables are useful on reports when the column data isn't mapped directly to a field in the database.
But instead, the data is a result of a process or operation. For example, suppose the column was an aggregation
of data from several columns. If a temporary table isn't used, the data must be handled by AL code.
For XMLPorts, if the data that you're importing has a different structure than the table in Dynamics 365 Business
Central that you want to insert it into, you can import the data into a temporary table. You can then modify the
data before inserting it into the database.

See Also
Get Started with AL
Table Object
Temporary Property
UseTemporary Property (Report)
UseTemporary Property (XMLPort)
Retaining table data after publishing
2/6/2023 • 4 minutes to read • Edit Online

When developing an extension, you debug several times using the F5 shortcut key, and you also test your app
by adding some sample data every time. To simplify the extension development process in Business Central, you
can synchronize the sample data specified in the extension when you do subsequent publishing from Visual
Studio Code.

How data synchronization works


The data synchronization between each publish is controlled by the schemaUpdateMode setting, which is specified
in the launch.json file. This setting consists of three options; Synchronize , Recreate , and ForceSync .
The default value for schemaUpdateMode is set to the Synchronize mode, which means that every time you
publish an extension to the development server, the data you entered previously stays. If you do not want to
synchronize the sample data with each publish, you can change the schemaUpdateMode setting from Synchronize
to, for example, Recreate with the syntax shown in the example below.

{
"type": "al",
"request": "launch",
"name": "your own server",
"server": "https://localhost",
"serverInstance": "Nav",
"authentcation": "UserPassword",
"startupobjectId": 22,
"schemaUpdateMode": "Recreate"
}

Recreate mode
When you set the schema update mode to Recreate , all the tables and table extensions are recreated at every
publish, which means that all the data in those tables are lost. This means that you will get empty records when
you publish your extension.

ForceSync mode
ForceSync is similar to the existing Synchronize schema update mode, but contains more freedom to make
schema changes while retaining data. To enable this mode, set schemaUpdateMode to "ForceSync" and then set
the "version" parameter in the app.json file to a fixed number. Data will be preserved in almost all cases with
the exception of changing the main table's primary key, in which case the data from the extension tables will be
lost. Field renames are allowed and supported in this mode, but the data can only be preserved if you maintain
the same ID for the field. If you change both the name and the ID of the field then the data will be lost.

IMPORTANT
This schema update mode is only meant for testing and development and should never be used in production.

In addition to the launch.json file setting, the ForceSync switch is available through the PowerShell cmdlet
Sync-NavApp –Mode ForceSync .
Things to be aware of
Synchronize is the default schema update mode for syncing the database and the extension. There are some
key factors to consider when you work with the Synchronize mode.
After publishing, the field data and the primary key information synchronizes with all the tables and the
table extensions. This means that you can do additions easily, but not deletions. Breaking changes are
never supported in synchronize mode. For example, you can add a field and sync that with the extension
just by pressing the F5 shortcut key, but if a field is removed then the table data cannot be synchronized.
If you, during development, for example, discover that you no longer want field X , and you then mark
field X as obsolete, you may still want to write an upgrade codeunit to move the data from the obsolete
field to a new field Y that you introduce. Later, the obsoleted field will not be available. But if you do not
want the data, you can choose to use the Recreate mode instead.
When you make changes to the data types, you can only enlarge the unit size, and not decrease the unit
size. For example, you can set a text type from Code[20] to Code[50] or Text[32] to Text[87] , and you
cannot set a text type from Code[50] to Code[30] or Text[87] to Text[40] .
For field data types, however, changing the length is not allowed. If you, for example, change version 1.0
of the field(50100; MyField; Text[50]) to field(50100; MyField; Text[150]) in version 2.0 it is
considered a breaking change. For more information, see AppSourceCop Rule AS0086.
Making major table structural changes could lead to compilation errors. For example, if you want to
update a primary key. In this case, the table data cannot be synchronized, and if you want to publish the
extension, you must change the schemaUpdateMode to Recreate . Likewise, changing the DataPerCompany
from true to false and from false to true is a schema-breaking change, and therefore not allowed
because it changes the number of tables per company.
For extensions built on Business Central Spring 2019 or earlier, if a table field has the SqlDataType set to
a value other than Varchar (which is the default), you must delete the SqlDataType property on the field,
otherwise, you will will not be able to successfully synchronize the extension.
If the SqlDataType property is still needed, you will have to create a new table in the extension that has
the same definition as the original table, and write upgrade code that migrates the data from the original
table to the new table. For more information, see Writing upgrade code.
Alternatively, if this is a development scenario, you can synchronize the extension using the ForceSync or
Recreate mode.

See Also
AL Development Environment
Upgrading Extensions
Debugging
Integrating Microsoft Dataverse for Extension
Development
2/6/2023 • 2 minutes to read • Edit Online

Develop extensions and streamline the workflow by synchronizing Microsoft Dataverse data with Dynamics 365
Business Central.
For developing extensions to integrate with sales data, you simply enable the tables used in Microsoft Dataverse.
The extension development process includes the following set of properties in Dynamics 365 Business Central
to enable field mapping. You can enable the field mapping by using the following properties. The tables are
extensible, so that you can update Microsoft Dataverse with data as well.

Associated table and field properties


The following properties are used for integrating with Microsoft Dataverse:

P RO P ERT IES A P P L IES TO DESC RIP T IO N

TableType Property Tables Specifies the table type. This enables


the table to integrate with the external
database. For example, CDS .

ExternalName Property Tables, Fields Specifies the name of the original table
in the external database when used as
a table property.

Specifies the field name of the


corresponding field specified in the
external table when used as a field
property.

ExternalAccess Property Fields Specifies the access to the underlying


Microsoft Dataverse table when
Microsoft Dataverse tables are
generated using the AL Table Proxy
Generator tool, see AL Proxy Table
Generator

ExternalType Property Fields Specifies the data type of the


corresponding column in the Microsoft
Dataverse table.

OptionMembers Property Fields Sets the option values for a field, text
box, or variable.

OptionOrdinalValues Property Fields Specifies the list of option values. You


can set this property, if the
ExternalType is set to Picklist .

Enabling the table


Typically in Microsoft Dataverse, tables handle the internal processes. In order to access to the underlying
Microsoft Dataverse table, you use the TableType property and select the value called CDS . This enables the
table as an integration table for integrating Dynamics 365 Business Central with Microsoft Dataverse. The table
is mainly based on a table in Microsoft Dataverse, such as the Accounts table.

Snippet support
Typing the shortcut ttable will create the basic layout for a table object when using the AL Language extension
in Visual Studio Code.

Example
In the following example, the SalesIntegration table uses the TableType and ExternalName properties to link
the underlying Microsoft Dataverse table for mapping the columns from the Sales table with the specified
fields.

table 50100 SalesIntegration


{
TableType = CDS;
ExternalName = 'Sales';

fields
{
field(1; ActualSales; Integer)
{
ExternalName = 'ActualSale';
ExternalAccess = Full;
ExternalType = 'String';
}

field(2; SalesCategories; Option)


{
ExternalName='SalesCategory';
ExternalAccess = Read;
ExternalType = 'Picklist';
OptionMembers = Manufacturing, Marketing, Support;
OptionOrdinalValues = -1, 1, 2;
}
}
}

See Also
Table Properties
TableType Property
AL Proxy Table Generator
Creating Filter Pages for Filtering Tables
2/6/2023 • 2 minutes to read • Edit Online

In AL code, you can use the FilterPageBuilder data type to create a filter page that enables users to set filters on
multiple tables. Filter pages contain one or more filter controls, where each filter control can be used to set
filters on a specific table. In the Business Central client, filter pages are generated at runtime and run in a modal
dialog box. The following figure illustrates a filter page that filters on the Item table.

To create a filter page, you use AL code and the methods that are available for the FilterPageBuilder Data Type.
The following code example shows the code that creates the filter page in the figure.

var
Item: Record Item;
Customer: Record Customer;
FilterPage: FilterPageBuilder;
FilterPageCaption: TextConst ENU = 'Customer and Item Filter Page';
begin
FilterPage.AddTable(Customer.TableCaption(), Database::Customer);
FilterPage.AddRecord(Item.TableCaption(), Item);
FilterPage.Addfield(Item.TableCaption(), Item."No.", '>100');
FilterPage.PageCaption := FilterPageCaption;
FilterPage.RunModal();
end;

See Also
FilterPageBuilder Data Type
Working With Media on Records
2/6/2023 • 8 minutes to read • Edit Online

This article describes how you can upload media, such as an image, to the database for displaying with records
in the client. There are two ways that you can upload media:
Use a BLOB data type
You add media to a BLOB data type field on the record. For more information, see BLOB Data Type.
Use a Media or MediaSet data type
This way enables you to store media in system tables of the database, and then reference the media from
application records. For example, you can:
Display media with records in list type pages, when the page is viewed in the Tile layout. For more
information, see Displaying Data as Tiles.
Display media on a card type page for a record.
Display media in a report.
Using the Media or MediaSet data type provides better performance than using a BLOB data type and is more
flexible in its design. With a BLOB data type, each time the media is rendered in the client, it's retrieved from the
SQL database server, which requires extra bandwidth and affects performance. With the Media and MediaSet
data types, the client uses media ID to cache the media data, which in turn improves the response time for
rendering the media in the user interface.

Using Media and Media Sets on records


Table fields support two data types for adding media to records: Media and MediaSet . With these data types,
you can import media directly from a file to a record, or media can be passed to the record in an InStream
object. Imported media is stored as an object in the system table 2000000184 Tenant Media of the tenant
database. Each media object is assigned a unique identifier (ID).

Media data type


The Media data type associates a record with a single media object. For example, you can use this data type to
display an image with each record in a list type page.
If a media object is added to Media data type field, the field references the media object by its ID.

NOTE
Starting with Business Central 2021 release wave 1, when importing Microsoft Word files (.docx), macro packages (VBA
code) will automatically be removed from the file when stored in the database. If macros are needed for end-user
scenarios, the macro must be in the Word template (.dotx) associated with the document being imported.

MediaSet data type


The MediaSet data type associates a record with one or more media objects. This association enables you to set
up a collection or catalog of media for a record. For example, you can use this data type to set up a slide show of
images for a record in a card type page.
If a media object is added to MediaSet data type field, the media object is assigned to a media set in the system
table 2000000183 Tenant Media Set . The media set is assigned a unique identifier, which is then referenced
from the field. The media set is created with the first file media object that you add on the record. Any other
media objects for the record are then associated with the same media set.
Indexing of media objects in a media set
A media set is an ordered list of media objects, determined by the order in which the media objects were added
to the media set. This order can't be changed. To identify this order, each media object is assigned an index
number, starting a 1. The first media added gets the index 1, the second media gets the index 2, and so on. If a
media object is removed from the set, the list is reindexed.

NOTE
If a MediaSet data type field is used in a report object, then only the first associated media file is displayed in the
generated report.

Supported Media (MIME) types


The media type, also referred to as the MIME (Multipurpose Internet Mail Extensions) type, is an Internet
standard to describe the contents of a file. Internet browsers use the MIME type to determine how to handle the
file. The Media and MediaSet datatypes support all recognized MIME types.
A MIME type is defined by two parts, the type and subtype, where the format is type/subtype . For example, the
MIME type for a JPEG image is image/jpeg. There are several types, including image, application, audio, video,
text, and more. Each MIME type is associated with one or more acceptable file extensions. The following table
lists some of the more common MIME types and their file extensions.

M IM E T Y P E F IL E EXT EN SIO N

image/bmp bmp

image/jpeg jpeg, jpg, jpe

image/gif gif

application/msword doc

application/octet-stream json

application/vnd.openxmlformats- docx
officedocument.wordprocessingml.document

application/vnd.ms-excel xls

application/vnd.openxmlformats- xlsx
officedocument.spreadsheetml.sheet

application/vnd.ms-powerpoint ppt

application/vnd.openxmlformats- pptx
officedocument.presentationml.presentation
M IM E T Y P E F IL E EXT EN SIO N

application/pdf pdf

application/xml xml

audio/mpeg mp3

audio/x-wav wav

video/mp4 mp4

video/x-msvideo avi

text/html htm, html

text/plain txt

NOTE
GIF type is not supported on reports. If you want to display an image on a report, use another supported type.
Files with extensions that are not recognized are also supported and can be imported. These are stored as BLOBs (binary
larger objects).

General procedure for adding media to records


The general procedure for setting up media on records is as follows:
1. Obtain the media file or files that you want to use on the record.
2. In AL, modify the table object to include a field that has the data type Media or MediaSet .
3. Add AL code that imports the media on the field.
The Media and MediaSet data types support several methods that you can use to manage the media on
records. See the next section for a complete list of methods with a link to more details, such as usage,
parameters, and sample code.
For example, you can create a codeunit that calls one of the import methods. Or, add a page action that
calls one of the methods.

AL methods
To get an overview of the methods that are related to the Media and MediaSet data types, see Media Data Type
and MediaSet Data Type.

Automatic deletion of unused Media objects


When a table record that contains a media object is deleted, the OnDelete trigger gets the media or media set's
ID. It then uses the ID to look for other references to the media object from the same field index in the same
table. If no other references are found, the media object is assumed to be unreferenced and it's deleted. The
runtime won't look in all tables in the database to see if a media object is referenced elsewhere, because doing
so would lower performance and result in costly SQL table scans. If media objects are to be shared between
tables, they should be shared through a reference table or by sharing the media set field content as described in
the next section.

Sharing Media objects between different tables


To maintain data integrity that's related to media object, it’s important to notice that the Media and MediaSet
data types are complex data types, which are referenced by an ID. The ID is stored in the record field that
contains the media object. If a simple copy operation is done to copy the media object from one media set field
to another, the ID is copied to the new field. But the application doesn't know that the media object is referenced
in two different fields, which causes issues when a row that contains the media ID is deleted.
To avoid unintentionally deleting referenced media objects, media sharing should be done by using the INSERT
method to insert the media (by its ID) into the new media set field. Using the INSERT method will create the
correct (new) MediaSet records in the system tables. The media object in one field won't be deleted if the media
object in the other field is deleted.
Example
This example copies a media set field called MediaSetField in table mediaSourceTable to a field in another table
mediaTargetTable . The FOR loop will iterate all media objects in the source, and then insert their ID in the target
field.

for index := 1 to mediaSourceTable.MediaSetField.COUNT do


mediaTargetTable.MediaSetField.INSERT(mediaSourceTable.MediaSetField.ITEM(index));
MediaTargetTable.Modify(true);

This example will create a new media set that contains the shared media object references. When you delete the
media set (by deleting the MediaTargetTable record), the runtime will detect that the media object is used in
multiple media sets, so it won't delete the media objects. The media objects might eventually be deleted when
the runtime can't find other references.

IMPORTANT
The simple field copy statement mediaTargetTable.MediaSetField := mediaSourceTable.MediaSetField; can only be
used if mediaTargetTable is declared as the same record subtype as mediaSourceTable , and the target and source field
IDs are the same.

Changing an RDLC report to use Media fields instead of BLOB fields


This section describes how to change an RDLC report that displays a BITMAP image (
<MIMEType>image/bmp</MIMEType> ) from BLOB data type field to use Media fields instead. The change requires that
you modify the report object's AL code and the report layout's RDLC file.
AL code changes
Media and MediaSet data types don't require CALCFIELDS to fetch data. So in the report AL triggers, remove the
CALCFIELDS operation on the field that contains the image.

RDLC layout changes


An RDLC layout will typically use base64 conversion on the BITMAP image. However, the media data types don't
require a base64 encoding. If a media field gets converted to a base 64 string, the report won't render the
image, and the output will show a missing picture bitmap.
So in this case, you'll have to change the layout's .rdlc file to use a direct field reference to the media, without the
base64 conversion. In the .rdlc file, the media reference is done in the <Value></Value> element of the
<Image></Image> element.
For example, suppose an image's <Value></Value> element is expressed like the following example:

<Value>=Convert.ToBase64String(Fields!CompanyInfo2Picture.Value)</Value>

To use a direct reference without the base64 conversion, change <Value></Value> element expression to:

<Value>=Fields!CompanyInfo2Picture.Value</Value>

See Also
BLOB Data Type
Media Data Type
MediaSet Data Type
Get, Find, and Next Methods
2/6/2023 • 3 minutes to read • Edit Online

The following methods are used to search for records:


Get
Find
Next

These methods are some of the most frequently used AL methods. When you search for records, you must
know the difference between Get and Find. You should also know how to use Find and Next in conjunction.

TIP
When using these methods, consider using the partial records methods to improve performance, especially when looping
through several records or when table extensions are defined on the table. For more information, see Using Partial
Records.

Get method
The Get Method (Record) retrieves one record based on values of the primary key fields.
Get has the following syntax.

[Ok :=] Record.Get([Value],...)

For example, if the No. field is the primary key of the Customer table and if you've created a record variable
called CustomerRec that has a subtype of Customer, then you can use Get in the following way.

CustomerRec.Get('4711');

The result is that the record of customer 4711 is retrieved.


Get produces a run-time error if it fails and the return value isn't checked by the code. In the previous example,
the actual code that you write should resemble the following.

if CustomerRec.GET('4711') then
.... // Do some processing.
else
.... // Do some error processing.

Get searches for a record without changing any current filters. Get always searches through all the records in a
table.

GetBySystemId method
APPLIES TO: Business Central 2019 release wave 2 and later

The GetBySystemId(Guid) retrieves a record based on the value of its SystemId field.
GetBySystemId has the following syntax:

RecordExists := Record.GetBySystemId(SystemId: Guid)

The following example gets the record that has the SystemId 5286305A-08A3-E911-8180-001DD8B7338E :

var
Customer: Record Customer;
Text000: Label 'Customer was found.';
begin
If Customer.GetBySystemId('{5286305A-08A3-E911-8180-001DD8B7338E}') then
Message(Text000);
end;

Similar to the Get method, GetBySystemId also searches for a record without changing any current filters.

Find methods
The Find Method (Record) locates a record in a table that is based on the values stored in the keys.
Find has the following syntax.

Ok := Record.Find([Which])

The Which parameter specifies how to perform the search. You can search for values that are greater than, less
than, or equal to the key value, or for the first or last record in a table.
The important differences between Get and Find are as follows:
Find uses the current filters.
Find can look for records where the key value is equal to, greater than, or smaller than the search string.
Find can find the first or the last record, depending on the sort order defined by the current key.
When you're developing applications in a relational database, there are often one-to-many relationships defined
between tables. An example could be the relationship between an Item table, which registers items, and a Sales
Line table, which registers the detailed lines from sales orders. One record in the Sales Line table can only be
related to one item, but each item can be related to any number of sales line records. You won't want an item
record to be deleted as long as there are still open sales orders that include the item. You can use Find to check
for open sales orders.
The OnDelete trigger of the Item table includes the following code that illustrates using Find.

SalesOrderLine.SetCurrentKey(Type,"No.");
SalesOrderLine.SetRange(Type,SalesOrderLine.Type::Item);
SalesOrderLine.SetRange("No.","No.");
if SalesOrderLine.Find('-') then
Error(Text001,TableCaption,"No.",SalesOrderLine."Document Type");

If you want to find the first record in a table or set, then use the FindFirst Method (Record). If you want to find
the last record in a table or set, then use the FindLast Method (Record).

Next method
The Next Method (Record) is often used with FIND to step through the records of a table.
Next has the following syntax.

Steps := Record.Next([Steps])

In the following example, Find is used to go to the first record of the table. Next is used to step through every
record, until there are no more. When there are no more records, Next returns a 0 (zero).

if (Rec.FindSet) then
repeat
// process record
until (Rec.Next = 0);

See Also
AL Methods
SystemId Field
Using Partial Records
2/6/2023 • 8 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

The partial records capability in Business Central allows for loading a subset of normal table fields when
accessing a SQL based data source. Using partial records improves performance of objects like reports and
OData pages - objects whose source code loops through records. It's particularly beneficial when table
extensions are used in the application.
Accessing a data source from AL code is typically done by using the record's methods Get, Find, Next, and so on.
Without using partial records, the runtime loads all normal fields when accessing the data source. Using the
partial records API, you can now select a set of fields and only load them.

API Overview
To accommodate partial record loading, the following methods are available on both the RecordRef and Record
data type in AL. These methods operate on the record instance that they're called on, changing the set of fields
to load until otherwise altered. The methods are divided into two groups: methods that pertain to subsequent
loads and methods that pertain to the currently loaded record.
Subsequent load methods

M ET H O D DESC RIP T IO N SEE M O RE

SetLoadFields Specifies a set of fields to be initially Record.SetLoadFields


loaded when the record is retrieved
from its data source. A call to this RecordRef.SetLoadFields
method will overwrite any fields that
were previously set to load.

AddLoadFields Adds fields to the current set of fields Record.AddLoadFields


to be initially loaded when the record
is retrieved from its data source. RecordRef.AddLoadFields
Subsequent calls to this method won't
overwrite fields that were previously
selected for loading.

Current load methods

M ET H O D DESC RIP T IO N SEE M O RE

AreFieldsLoaded Checks whether the specified fields are Record.AreFieldsLoaded


all initially loaded.
RecordRef.AreFieldsLoaded

LoadFields Accesses the table's corresponding Record.LoadFields


data source to load the specified fields.
RecordRef.LoadFields

A record instance that has been previously loaded with fields can be reset to a non-partial load either by calling
Record.SetLoadFields without any parameters, or by calling Reset. After being reset, subsequent loads will
behave as if SetLoadFields hadn't previously been called on the record instance.

Example
The following code shows a way to load only a single field from the Item table for computing the arithmetic
mean.

procedure ComputeArithmeticMean(): Decimal;


var
Item: Record Item;
SumTotal: Decimal;
Counter: Integer;
begin
Item.SetLoadFields(Item."Standard Cost");
if Item.FindSet() then begin
repeat
SumTotal += Item."Standard Cost";
Counter += 1;
until Item.Next() = 0;
exit(SumTotal / Counter);
end;
end

Notice that the call to SetLoadFields occurs before the data fetching operations. This call determines which fields
are needed for the FindSet call. You use the same pattern for AddLoadFields calls.

Usage guidelines
This feature gives you the ability to limit the fields that load for a record to only those fields that are necessary.
In general, loading fewer fields will make operations faster. But the most significant performance gains can be
seen with table extensions - by not loading unnecessary fields in table extensions. Table extensions that don't
have any fields for loading won't be part of the data join, which saves time.

TIP
Testing on the previous example code showed that the execution time for loading only the "Standard Cost" field was nine
times faster than loading all normal fields. Your performance numbers will vary depending on the machine and the setup
with the SQL database.

For performance reasons, it's not recommended to use partial records on a record that will do inserts, deletes,
renames, field transfers, or copies to temporary records. All these operations require that all fields on the record
are loaded, so the platform will emit a JIT load if they're not already loaded. A JIT load requires to access the data
source again, this cost is larger than the gains of loading fewer fields. For this reason, the feature is especially
advantageous in reading-based scenarios.

Just-in-time (JIT) loading


When a record is loaded as a partial record, the obvious question is: What happens when accessing a field that
hasn't been selected for loading? The answer is JIT loading. The platform, in such a case, does an implicit Get on
the record and loads out the missing field.
When JIT loading occurs, another access to the data source is required. These operations tend to be fast because
they're Get calls. Get calls can often be served by the server's data cache or can be resolved as a clustered index
operation on the database.
A JIT load may fail for multiple reasons, like:
The record has been modified between the original load and the subsequent JIT load.
The record has been deleted between the original load and the subsequent JIT load.
The record has been renamed between the original load and the subsequent JIT load.

Iterating over records


When iterating over records in the database, an enumerator is created based on selected fields. Then, a row is
fetched when Next is called. This behavior is an optimization that allows for large parts of the operation to be
done only once.
Certain operations will invalidate the enumerator and force the creation of a new one, which adds some
overhead. As long as the enumerator isn't invalidated too frequently, this model is an effective optimization.
When accessing fields that aren't loaded, the platform does a JIT load, followed by an update of the enumerator.
This process eliminates the need to trigger a JIT load on subsequent iterations.
When passing a record by value, without using a var parameter, a new copy of the record is created. The original
record and its copy don't share filters, fields selected for load, and so on. So accessing an unloaded field will
trigger a JIT load. But it won't update the enumerator, which means future iterations will also require JIT load.
There are a few options to remedy this situation:
Pass the record reference using var parameter allows for updating of enumerator.
Call AddLoadFields(fieldnames) on the original record before passing by value.
Before calling Get, Find, Next, and so on, use the SetLoadFields(fieldnames) to set all fields needed for load.

Preventing inconsistent read and JIT loading errors


Seeing the error Inconsistent read of field(s):… means that a read record has changed in the database
sometime between the initial load and a subsequent load. When a subsequent load (JIT load) occurs, extra fields
are loaded, and all previously loaded fields are checked for consistency to verify that they haven't changed. For
example, suppose the Amount field in a table had the value of 42 on the initial load. But at sometime before the
subsequent load, another user changed the value in the database to 9001.
You could categorize this error as a read skew consistency error. The platform, in this case, doesn't know whether
the previously executed code made decisions based on the value being 42. So, instead of potentially ending up
with inconsistent data, the platform invokes error handling by throwing an error.
Another error related to the Inconsistent read of field(s):... error is the JIT loading of field(s): ... failed ...
error. This error is a more generic error that can happen for multiple reasons during a JIT load. But the most
frequent cause is that the record has been deleted in the database. It's similar the Another User has Modified
the record error you'll get when a record is modified, but the platform detects newer data in the database. All
these errors are the result of a race condition, meaning they depend on whether other users are also interacting
with the same data concurrently.
To prevent these errors, avoid JIT loads if you can. If there are no subsequent loads (JIT), the previously described
race condition will never occur. To avoid JIT loads, follow these guidelines:
On the first load, select all and only the necessary fields by using SetLoadFields calls or subsequent
AddLoadFields calls.
When the platform implicitly uses partial records, add the extra fields by calling AddLoadFields from the
OnPreDataItem trigger on reports or from the OnOpenPage trigger on OData pages.
For more information, see Reports and OData pages. Optionally, you can add the fields as a data column on
reports or fields on OData pages.
Partial records applied by platform
The platform will automatically apply partial records to certain types of AL objects based on their metadata. This
is currently done in four places: reports, OData pages, list and listpart pages, and table relation-based lookups.
Reports
When loading data for a report, the fields that are referenced in data columns on a data item will automatically
be selected for load. This includes references in nested data items.
Other fields aren't selected for load, even if they may be used in triggers. However, you can add extra fields the
following ways:
Add the field as a column in the data set.
Add the field to the set of fields to load via the AddLoadFields method on the OnPreDataItem trigger.
The following example code snippet illustrates how to use the AddLoadFields method on a report's
OnPreDataItem trigger to add a field for loading:

trigger OnPreDataItem()
begin
CurrencyDataItem.AddLoadFields(CurrencyDataItem."ISO Numeric Code");
end;

trigger OnAfterGetRecord()
begin
if (CurrencyDataItem."ISO Numeric Code" <> 'DKK') then begin
CurrReport.Skip();
end;
end;

OData pages
For pages opened by OData service calls, the page's metadata is used to define which fields to show. In this case,
the fields referenced in the page’s layout are loaded as a minimum. More fields may be required, for example, to
enable subpage linking.
Like with reports, other fields aren't selected for load, even if they may be used in triggers. But you can add extra
fields the following ways:
Add the field to the page layout.
Add the field to the set of fields to be loaded via the AddLoadFields method on the OnFind trigger.
List and ListPart pages
Partial records are automatically applied based on the page’s metadata for List and ListPart page types that are
opened in the web client. As with OData pages, the page's definition is used to select which fields to load. More
fields may be required, for example, to enable subpage linking.
To extend which fields will be loaded, you can use the same approach as with OData pages.

NOTE
OnFindRecord and OnNextRecord triggers conflict with partial record feature, so if either of these triggers is defined in the
metadata, the partial record feature won't be applied and it fall back to standard loading behavior.

Table relation-based lookups


Lookups that are based on table relations and not explicit lookup pages will automatically generate the set of
fields to load by using the same logic as for determining which fields to shown. Because these lookups don't
have a defined page, it isn’t possible, or necessary, to overrule the set of fields.

See Also
FAQ for Partial Records
Performance Articles For Developers
Get, Find, and Next Methods
Configuring Business Central Server
FAQ for Partial Records
2/6/2023 • 2 minutes to read • Edit Online

This article answers some of the most typical questions about the partial records capability in Business Central.

Do I need to change any code to keep my solution functional?


No. If a field that's not selected for loading is accessed, the data will be fetched automatically for the current
record. The field will then be selected for loading on future requests by using this record instance. However, you
may still get the message Record has been modified by another user, like you could before. But now, the
message can also appear in read-only scenarios where the record isn't locked.

Where is "Partial Records" applied? To all records instances?


Currently, the partial records capability is only implicitly used on report data items, OData pages, List pages,
ListPart pages and table relation-based lookups. The behavior for all other record instances is as before, that is,
all fields will be loaded. However, as an AL developer, use in your own code to improve performance in looping
code.

What happens when accessing fields not selected for load?


The platform will load any fields not selected for loading when accessed, making it seem like the field was
already loaded.

What happens if the record has been modified or deleted in between


the original load and JIT load?
The platform will validate that either the record is unchanged, or no change has been made to read fields.

What's a JIT load?


The platform determines that a field, which isn't currently loaded, is needed. Then it loads the field.

Can I optimize my code, so that I can avoid an extra database call to


load my field?
Yes. You can add your field to the list of fields selected for loading by using the AddLoadFields method.

Which fields can be selected not to be loaded?


Any field that isn't a FlowField, FlowFilter, Primary Key, Timestamp, SystemId, Audit Fields, or Blobs.

How do partial records interact with table extensions?


When no fields from a table extension are selected for loading, then table extension data isn't joined, which
saves time.

What's the performance overhead of determining the fields necessary


for a record?
For reports, a calculation takes place at compile time and once per data item type per report execution. For
OData pages, the calculation takes place at compile time and once per request segment.
Compared to the time it takes to fetch data, the overhead is insignificant.

Can I disable partial records in certain scenarios?


With Business Central on-premises, you can turn off partial records by using Enable Par tial Records
setting of Business Central Server. See Configuring Business Central Server .
With Business Central online, you can call the SetLoadFields method with no fields. Calling an empty
SetLoadFields method will revert the behavior to what it was before Business Central 2020 release wave
2.

See Also
Performance Articles For Developers
Get, Find, and Next Methods
Configuring Business Central Server
Queries in Business Central
2/6/2023 • 3 minutes to read • Edit Online

Queries enable you to retrieve records from one or more tables or data sources and then combine the data into
rows and columns in a single dataset. Queries can also perform calculations on data, such as finding the sum or
average of all values in a column of the dataset.

Query Types
There are two types of query objects: normal and API.
A normal query retrieves records from business data tables in the Dynamics 365 Business Central database,
and can be used to display data in the user interface. This type of query is created by a query object. For
more information, see Query Object.
An API query is used to generate web service endpoints and this type of page cannot be displayed in the user
interface. A query of the API type can be used to join data from different data sources. The data can only be
viewed. For information about creating a query of the type API, see API Query Type.
Query usages
The following examples show how you can use queries in your Dynamics 365 Business Central application.
Creating charts that are based on a query instead of a table.
Saving a query as an .xml or .csv file. For example, you can use the SAVEASXML method to create an .xml
file that contains the resulting dataset of a query. You can use the .xml file to integrate with external
applications.
Exposing data as an OData web service. You can register and publish a query as a web service in the
same way that you can register and publish pages or codeunits as web services. You use the Web
Ser vices page to register and publish pages, codeunits, or queries. After you expose a query as a web
service, you can import it into other applications.
Using the query as a data source for a page. To do this, you have to copy the query resulting dataset into
a temporary table and set it as the source table for the page.
Using the query as a data source for a report. To do this, create a global variable that points to the query.
Then use the variable in the report dataset. For more information see, Defining a Report Dataset.
Performing calculations on data such as computing sums and averages. For more information, see Query
Totals and Grouping.
Replacing nested loops that use record variables to retrieve or to detect duplicate records. For more
information, see Using Queries Instead of Record Variables.

Query Data Type


The query resulting dataset cannot be used directly by other objects such as pages and reports. Instead, you
must create a Query Data Type instance and apply methods for handling the data from the query object. You
must first call the OPEN Method to be able to perform actions such as reading the dataset or setting filters and
you must use the CLOSE Method when you are finished. You can write this code in a codeunit, for example. The
following example illustrates how to do this.
var
MyQuery: Query "Customer SalesQuantity";
Text000: Label 'Customer name = %1, Quantity = %2';
begin
// Sets a filter to display only sales quantities greater than 20.
MyQuery.SETFILTER(Quantity, '>20');
// Runs the query.
MyQuery.Open;
// Reads each row in the dataset and displays a message with column values.
// Stops reading when there are no more rows remaining in the dataset (READ is FALSE).
while MyQuery.Read do
begin
Message(Text000, MyQuery.Name, MyQuery.Quantity);
end;
MyQuery.Close;
end;

See Also
Query Object
Linking and Joining Data Items
Aggregating Data in Query Objects
Query Properties
Developing Extensions
AL Development Environment
Utilizing Read Scale-Out for Better Performance
Query Object
2/6/2023 • 4 minutes to read • Edit Online

Business Central query objects enable you to retrieve records from one or more tables and then combine the
data into rows and columns in a single dataset. Query objects can also perform calculations on data, such
finding the sum or average of all values in a column of the dataset.
There are two types of query objects: normal and API. This article describes normal query objects, which can be
used to display data in the user interface. API query objects are used to generate web service endpoints and
cannot be displayed in the user interface. For information about creating a query of the type API, see API Query
Type.

Creating a query object


A query object is comprised mainly of two different types of elements: dataitems and columns. A dataitem
specifies the table to retrieve records from. A column specifies a field of the table to include in the resulting
dataset of a query. The basic steps to create a query object are as follows:
1. Add the query keyword, followed by the elements control.
2. Build the dataset by adding dataitem controls and column controls within the elements control.
The hierarchy of the dataitem and column controls is important because it will determine the sequence
in which data items are linked, which in turn will control the results. Working from top-to-bottom, you
start by adding the dataitem control for first table that you want in the dataset, then add column
controls for each table field that you want to include in the dataset. For the next table, you add another
dataitem control that is embedded within the first dataitem control, then add column controls as
needed. You continue this pattern for additional tables and fields.
3. When you have specified the dataitem and column elements, create links and joins between the
dataitem elements.

Dataitem links and joins determine which records to include in the dataset based on the values of a
common field between dataitems. You set a link between one or more fields of the dataitem tables with
the DataItemLink Property and you define the type of the link using the SQLJoinType Property. Both
properties must be set on the lower dataitem of the query object. For more information, see Linking and
Joining Data Items.
The following shows the basic structure of a query object.
query ID Name
{

elements
{
dataitem(DataItem1; Table1)
{
column(Column1; Field1)
{
}
column(Column2; Field2)
{
}
dataitem(DataItem2; Table2)
{
// Sets a link between FieldY of Table2 and FieldX of Table1.
DataItemLink = FieldY = DataItem1.FieldX;
//The dataset contains records from Table1 and Table2 where a match is found between FieldY
and FieldX.
SqlJoinType = InnerJoin;

column(Column1; Field1)
{
}
dataitem(DataItem3; Table3)
{
DataItemLink = FieldZ = DataItem2.FieldY;
SqlJoinType = InnerJoin;
column(Column1; Field1)
{
}
}
}
}
}
}

NOTE
Extension objects can have a name with a maximum length of 30 characters.

Snippet support
Typing the shortcut tquery will create the basic layout for a Query object when using the AL Language
extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Query example
The following example shows a query that displays a list of customers with sales and profit figures. The query
primarily retrieves fields from the Customer table, but also displays fields from the Salesperson Purchaser
and Countr y Region tables.
The query also uses the DataItemLink property to create a link between the Customer table, Salesperson
Code field and the Salesperson Purchaser table, Code fields and a link between the Customer table,
Countr y/Region Code field and the Countr y/Region table, Code field.

query 50102 "Top Customer Overview"


{
QueryType = Normal;
Caption = 'Top Customer Overview';

DataAccessIntent = ReadOnly; // use this to read data from the secondary database replica to speed up
performance

elements
{
dataitem(Customer; Customer)
{
column(Name; Name)
{
}
column(No; "No.")
{
}
column(Sales_LCY; "Sales (LCY)")
{
}
column(Profit_LCY; "Profit (LCY)")
{
}
column(Country_Region_Code; "Country/Region Code")
{
}
column(City; City)
{
}
column(Global_Dimension_1_Code; "Global Dimension 1 Code")
{
}
column(Global_Dimension_2_Code; "Global Dimension 2 Code")
{
}
column(Salesperson_Code; "Salesperson Code")
{
}
dataitem(Salesperson_Purchaser; "Salesperson/Purchaser")
{
DataItemLink = Code = Customer."Salesperson Code";
column(SalesPersonName; Name)
{
}
dataitem(Country_Region; "Country/Region")
{
DataItemLink = Code = Customer."Country/Region Code";
column(CountryRegionName; Name)
{
}
}
}
}
}
}
IMPORTANT
You cannot run a query that gets data from both the application database and the business data database. This also
applies to single-tenant deployments so that you do not have to rewrite queries if you decide to export the application.
For a description of which tables are considered part of the application database, see Separating Application Data from
Business Data.

See Also
Linking and Joining Data Items
Aggregating Data in Query Objects
Query Objects and Performance
Query Properties
Query DataAccessIntent
Developing Extensions
AL Development Environment
API Query Type
Linking and Joining Data Items to Define the Query
Dataset
2/6/2023 • 11 minutes to read • Edit Online

Business Central queries enable you to retrieve records from one or more tables and combine the specific
records into rows in a single dataset. In AL, each table is specified as a data item. The data included in the dataset
is a result of how the data items are linked and joined together.

TIP
The concept of linking and joining data items in AL is similar to Join clauses in SQL Select statements on tables in SQL
Server. For those familiar with SQL Joins, when describing links and joins in AL, this article provides the equivalent SQL
SELECT statement in most cases.

Sample Tables and Query


To demonstrate data item links and joins, this article uses the following sample tables and query.
Salesperson/Purchaser Table
The Salesperson/Purchaser table contains a list of salespersons. Each salesperson is identified by a unique
code. The following is a simplified version of the Salesperson/Purchaser table for demonstration purposes.

C O DE NAME

AA Annette

BB Bart

DD Debra

JJ John

Sales Header Table


The Sales Header table contains a list of sales orders. Each sales order has a unique number, includes the name
of the customer to sell to, and is assigned to a salesperson by the Salesperson_Code column. The following is
a simplified version of the Sales Header table for demonstration purposes.

N O. SEL L - TO C USTO M ER N A M E SA L ESP ERSO N C O DE

1000 Autohaus AA

2000 Blanemark DD

3000 Candoxy JJ

4000 New Concepts

Sample Query
The following query object links the Sale Header table with the Salesperson/Purchaser table on the
Salesperson_Code and Code fields, as specified by the DataItemLink Property. In the example, the
SQLJoinType Property is set to InnerJoin .

query 50100 "Sample Query"


{
QueryType = Normal;
Caption = 'Sales Overview';

elements
{
dataitem(Salesperson_Purchaser; "Salesperson/Purchaser")
{
column(Salesperson; Name)
{

}
dataitem(Sales_Header; "Sales Header")
{
DataItemLink = "Salesperson Code" = Salesperson_Purchaser.Code;
// Change the SqlJoinType value to suit the desired results: LeftOuterJoin, InnerJoin,
RighOuterJoin, FullJoin, CrossJoin.
SqlJoinType = InnerJoin;

column(Order_Number; "No.")
{

}
column(Sell_to_Customer; "Sell-to Customer Name")
{

}
}
}
}
}

How to link and join data items


When you add data items to a query object in AL, you define them in a specific hierarchy, one after another. Each
lower data item is embedded within the definition of the upper data item. The order of the data items
determines the sequence in which data items are linked and joined to produce the results in the dataset.
In short, to join two data items, you set the DataItemLink and SqlJoinType properties on the lower data item in
the query object.

NOTE
In the sections that follow, some examples illustrate the use of either the WHERE clause and FROM clause to get the
same results. However, for better performance, we recommend using a FROM clause wherever possible.

Set the DataItemLink Property


The DataItemLink Property sets up a reference or association between one or more fields in the source table of a
lower data item tables with a field in the source table of the upper data item. In a query, two data item tables
typically will have columns that have values that are common to both tables. For example, the Salesperson
table and Sales Header table have the Code column and Salesperson_Code column in common. To create a
link between these two tables, you could set the DataItemLink property of the Sales Header data item as
follows:
DataItemLink = "Salesperson Code" = Salesperson_Purchaser.Code;

The DataItemLink Property sets up an "equal to" (=) comparison condition between two columns of the data
items. When the query is run, the query compares each row of the two data items to find records that having
matching values for the columns. Records that have matching column values are combined into a row in the
resulting dataset. In some cases, there will be records that don't have matching values. You use the SqlJoinType
Property to include records that don't have matching column values.
Set the SqlJoinType Property
The SqlJoinType Property determines which records to combine into the results, based on the values of the
fields linked by the DataItemLink property. You use this property to limit the records that are included in the
resulting dataset based on the specified conditions. By default, the SqlJoinType property is LeftOuterJoin , so if
you omit this property, a LeftOuterJoin is performed.

TIP
In SQL join statements, tables are designated as either left or right. In AL query objects, because data items are arranged
vertically, when joining data items, the left corresponds to the upper data item (table) and right corresponds to the lower
data item (table).

Linking More Than Two Data Items


A query links data items in the order that they appear in AL, starting from the top and then working downward.
When you have more than two data items, lower data items are linked to the resulting dataset of the linked data
items above it. For example, when you link the first two data items, the query generates a dataset. When you
add another data item, it's linked to the dataset of the first linked pair of data items, where it applies the
conditions that are specified by its DataItemLink Property and SqlJoinType Property. The following code adds
another data item to the sample query:
query 50100 "Sample Query"
{
QueryType = Normal;
Caption = 'Sales Overview';

elements
{
dataitem(Salesperson_Purchaser; "Salesperson/Purchaser")
{
column(Salesperson; Name)
{

}
dataitem(Sales_Header; "Sales Header")
{
DataItemLink = "Salesperson Code" = Salesperson_Purchaser.Code;
SqlJoinType = InnerJoin;

column(Order_Number; "No.")
{

}
column(Sell_to_Customer; "Sell-to Customer Name")
{

}
dataitem(Sales_Line; "Sales Line")
{
DataItemLink = "Sell-to Customer No." = Sales_Header."Sell-to Customer No.";
}
}
}
}
}

This pattern continues for each extra data item.

InnerJoin
InnerJoin creates a dataset by combining records from data item tables where a match is found between the
columns that are linked by the DataItemLink Property of the lower data item. Inner Join uses an "equal to"
comparison operator to match rows from the lower data item table with rows from the upper data item table
that is based on the values of the linked columns.
Each pair of matching records is combined into a row in the dataset.
Records from the upper and lower data item tables that don't have a matching column in the lower data
item table are excluded from the resulting dataset.
The following illustration shows an InnerJoin type between tables A and B. The shaded area indicates the
records that are included in the resulting dataset.

Dataset Example
The following table shows the resulting dataset for an InnerJoin between the Sales Header table and
Salesperson/Purchaser table in sample query.
SA L ESP ERSO N O RDER_N UM B ER SEL L _TO _C USTO M ER

Annette 1000 Autohaus

Debra 2000 Blanemark

John 3000 Candoxy

The records for Bar t in the Salesperson table and New Concepts in the Sales Header table don't have
matching records in the opposing table, so they are excluded from the resulting dataset.
SQL SELECT Statement for Inner Join
To specify an inner join with an SQL statement, you can do either of the following:
Use a WHERE clause.
Use the INNER JOIN condition with an ON clause.
The following two examples show how to create an inner join on the Salesperson/Purchaser and Sales
Header tables with SQL statements. These two statements result in the same dataset.

SELECT "Salesperson/Purchaser".Name, "Sales Header"."No.", "Sales Header"."Sell-to Customer Name"


FROM "Salesperson/Purchaser" INNER JOIN "Sales Header"
ON "Salesperson/Purchaser".Code = "Sales Header"."Salesperson Code"

SELECT "Salesperson/Purchaser".Name, "Sales Header"."No.", "Sales Header"."Sell-to Customer Name"


FROM "Salesperson/Purchaser", "Sales Header"
WHERE "Salesperson/Purchaser".Code = "Sales Header"."Salesperson Code"

LeftOuterJoin
A LeftOuterJoin resembles the InnerJoin except that the resulting dataset set contains every record from the
upper data item table, even if a record does not have a matching value in the lower data item for columns that
are linked by the DataItemLink Property.
For each record in the upper data item, a row is added in the dataset that combines columns from the
upper and lower data item.
When a record in the upper data item table has no matching record in the lower data item table, columns
coming from the lower data item table have null values.
The following illustration shows a LeftOuterJoin type between tables A and B. The shaded area indicates the
records that are included in the resulting dataset. In the sample query, the Salesperson/Purchaser table is
considered the left table.

Dataset Example
The following table shows the resulting dataset for a LeftOuterJoin between the Sales Header table and
Salesperson/Purchaser table in sample query.
SA L ESP ERSO N O RDER_N UM B ER SEL L _TO _C USTO M ER

Annette 1000 Autohaus

Bart null null

Debra 2000 Blanemark

John 3000 Candoxy

The record for Bar t in the Salesperson/Purchaser table does not have a matching record in the Sales Header
table, so a row is included but the columns from the Sale Header table are given null values. The record for
New Concepts in the Sale Header table is not included in the resulting dataset because it does not have a
matching column in the Salesperson/Purchaser table.
SQL SELECT Statement for Left Outer Join
To specify a left outer join with an SQL statement, you use the LEFT OUTER JOIN condition.
The following example shows how to create a left outer join on the Salesperson/Purchaser and Sales
Header tables by using a SQL statement.

SELECT "Salesperson/Purchaser".Name, "Sales Header"."No.", "Sales Header"."Sell-to Customer Name"


FROM "Salesperson/Purchaser" LEFT OUTER JOIN "Sales Header"
ON "Salesperson/Purchaser".Code = "Sales Header"."Salesperson Code"

RightOuterJoin
A RightOuterJoin resembles the inner join except that the resulting dataset set contains every record from the
lower data item table, even if a record does not have a matching value in the upper data item for columns that
are linked by the DataItemLink Property.
For each record in the lower data item, a row is added in the dataset that combines columns from the
lower and upper data item tables.
When a record in the lower data item table has no matching record in the upper data item table, columns
coming from the upper data item table have null values.
The following illustration shows a RightOuterJoin type between tables A and B. The shaded area indicates the
records that are included in the resulting dataset.

Dataset Example
The following table shows the resulting dataset for a RightOuterJoin between the Salesperson/Purchaser
table and Sales Header table in the sample query. The Sales Header table is considered the right table.

SA L ESP ERSO N O RDER_N UM B ER SEL L _TO _C USTO M ER

Annette 1000 Autohaus


SA L ESP ERSO N O RDER_N UM B ER SEL L _TO _C USTO M ER

Debra 2000 Blanemark

John 3000 Candoxy

null 4000 New Concept

The record for New Concepts in the Sales Header table does not have a matching record in the
Salesperson/Purchaser table, so a row is included but the columns from the Salesperson/Purchaser table
are given null values. The record for Bar t in the Salesperson/Purchaser table is not included in the resulting
dataset because it does not have a matching column in the Sales Header table.
SQL SELECT Statement for Right Outer Join
To specify a right outer join with an SQL statement, you use the RIGHT OUTER JOIN condition.
The following example shows how to create a right outer join on the Salesperson/Purchaser and Sales
Header tables by using a SQL statement.

SELECT "Salesperson/Purchaser".Name, "Sales Header"."No.", "Sales Header"."Sell-to Customer Name"


FROM "Salesperson/Purchaser" RIGHT OUTER JOIN "Sales Header"
ON "Salesperson/Purchaser".Code = "Sales Header"."Salesperson Code"

FullOuterJoin
A FullOuterJoin contains all the records from the upper data item table, and all records from the lower data
item, including records that don't have a matching value for columns that are linked by the DataItemLink
Property.
Each pair of records from the data items that have matching column values are combined into a row in
the dataset.
Records from the upper data item table that do have a matching column are included in a row, where the
columns from lower data item table have null values.
Records from the lower data item table that do have a matching column are included in a row, where the
columns from upper data item table have null values.
The following illustration shows a FullOuterJoin type between tables A and B. The shaded area indicates the
records that are included in the resulting dataset.

Dataset Example
The following table shows the resulting dataset for a full outer join between the Sales Header table and
Salesperson/Purchaser table in sample query.

SA L ESP ERSO N O RDER_N UM B ER SEL L _TO _C USTO M ER

Annette 1000 Autohaus


SA L ESP ERSO N O RDER_N UM B ER SEL L _TO _C USTO M ER

Bart null null

Debra 2000 Blanemark

John 3000 Candoxy

null 4000 New Concept

The records for Bar t in the Salesperson/Purchaser table and New Concepts in the Sales Header table are
included in a row, even though they not have matching values for columns.
SQL SELECT Statement for Full Outer Join
To specify a full outer join with an SQL statement, you use the FULL OUTER JOIN condition.
The following example shows how to create a full outer join on the Salesperson/Purchaser and Sales
Header tables by using a SQL statement.

SELECT "Salesperson/Purchaser".Name, "Sales Header"."No.", "Sales Header"."Sell-to Customer Name"


FROM "Salesperson/Purchaser" FULL OUTER JOIN "Sales Header"
ON "Salesperson/Purchaser".Code = "Sales Header"."Salesperson Code"

CrossJoin
A CrossJoin contains rows that combine each row from the upper data item table with each row from a lower
data item table. Cross joins are also called Cartesian products. A cross join does not apply any comparisons
between columns of data items, so the DataItemLink Property is left blank.
Dataset Example
The following table shows the resulting dataset for a CrossJoin between the Sales Header table and
Salesperson/Purchaser table in sample query.

SA L ESP ERSO N O RDER_N UM B ER SEL L _TO _C USTO M ER

Annette 1000 Autohaus

Annette 2000 Blanemark

Annette 3000 Candoxy

Annette 4000 New Concept

Bart 1000 Autohaus

Bart 2000 Blanemark

Bart 3000 Candoxy

Bart 4000 New Concept

Debra 1000 Autohaus


SA L ESP ERSO N O RDER_N UM B ER SEL L _TO _C USTO M ER

Debra 2000 Blanemark

Debra 3000 Candoxy

Debra 4000 New Concept

John 1000 Autohaus

John 2000 Blanemark

John 3000 Candoxy

John 4000 New Concept

SQL SELECT Statement for Cross Join


To specify a cross join with a SQL statement, you can do either of the following:
Use the CROSS JOIN condition
Create an implicit join, which has no join condition, without using a WHERE clause
The following examples shows how to create a cross join of the Salesperson/Purchaser and Sales Header
tables by using a SQL statement.

SELECT "Salesperson/Purchaser".Name, "Sales Header"."No.", "Sales Header"."Sell-to Customer Name"


FROM "Salesperson/Purchaser" CROSS JOIN "Sales Header"

SELECT "Salesperson/Purchaser".Name, "Sales Header"."No.", "Sales Header"."Sell-to Customer Name"


FROM "Salesperson/Purchaser", "Sales Header"

See Also
Query Object
Filtering Queries
Aggregating Data
Filtering in Query Objects
2/6/2023 • 8 minutes to read • Edit Online

You specify filters in a query to restrict the data in the resulting dataset. A filter applies conditions on fields in a
table that is associated with the query. For a record to be included in the resulting dataset, its values in these
fields must meet the conditions of the filter.

Overview
There are different ways to filter on fields of a query. You can set up filters on a field directly in the query object
or use the AL filter methods that are outlined in the following table.

F ILT ER DESC RIP T IO N

Filter directly on a data item in query object You can set the DataItemTableFilter property of a data item
to filter on a field in the table of the data item. You can apply
the filter to any field in the table, not just fields that are
defined as columns in the resulting dataset. A data item filter
can't be overwritten from AL code.

See Filtering on data items in a query object.

Filter directly on a column in a query object You can set the ColumnFilter property of a column control
to filter on the source field of the column. A filter on a
column can be overwritten by the SETFILTER and SETRANGE
methods from AL code.

See Filtering on columns and filter rows in query object.

Add a filter row to a query object A filter row lets you add a filter on a field that will not be
included in the resulting dataset, but can be changed from
AL code. To set up a row filter add a filter control
referencing the field that you want to filter and then set its
ColumnFilter Property. A filter row is like a data item filter
except a filter on a filter row can be overwritten by the
SETFILTER and SETRANGE methods from AL code.

See Filtering on columns and filter rows in query object.

Use SETFILTER or SETRANGE method calls You can call the SETFILTER method method from AL code to
set a filter on a field that is exposed through a column or
filter row. The filter that is set by the SETFILTER method will
overwrite any filter that is applied to a column or filter row
on the same field by the ColumnFilter Property.

You can call the SETRANGE method method from AL code to


set a filter on a field that is exposed through a column or
filter row. The filter that is set by the SETRANGE method will
overwrite any filter that is applied to column or filter row on
the same field.

See Filtering using SETFILTER and SETRANGE methods.

Filtering on data items in a Query object


To specify filters on a data item, you set the DataItemTableFilter property of a data item. DataItemTableFilter
property has the following syntax:

DataItemTableFilter = String;

Where String is the filter expression.


You can apply a filter on any field in a table, not just those fields that are represented by a column in the query
object.
A data item filter is static which means that it can't be overwritten by the ColumnFilter Property, filter
controls or by the SETFILTER or SETRANGE methods in AL code. If one of these filter types is applied to the same
field as the data item filter, then the filters are combined. In logical terms, this combination corresponds to an
"AND" operation. For example, if the data item filter applies a filter on a field to include values greater than 10
(>10) and a column filter applies a filter on the same field to include values less than fifty (<50), then the
resultant filter includes values that are greater than 10 and less than fifty (10< value <50).
The DataItemTableFilter Property corresponds to a WHERE clause in an SQL SELECT statement. For more
information, see Equivalent SQL SELECT Statements for Query Filters.
Example
The following query object links table 18 Customer and table 37 Sales Line to get the number of line items in
each sales for customers. The DataItemTableFilter property is used to only include rows in which the number
of line items is greater than 10.

query 50100 "Customer_Sales_Quantity"


{
QueryType = Normal;

elements
{
dataitem(C; Customer)
{
column(Customer_Number; "No.")
{
}

column(Customer_Name; Name)
{
}

dataitem(SL; "Sales Line")


{
DataItemLink = "Sell-to Customer No." = c."No.";
SqlJoinType = InnerJoin;
DataItemTableFilter = Quantity = filter(> 10);

column(Qty; Quantity)
{
}
}
}
}
}

Filtering on columns and filter rows in query object


Unlike data item filters, filters on a column or filter row are dynamic and can be overwritten from AL code at
runtime by a call to the SETFILTER or SETRANGE method, if the method sets a filter on the same field.
You use filters on a column to filter on fields that are included in the dataset. To apply a filter on a column, you
set the ColumnFilter Property of the column. You can apply a filter on any column, including aggregated
columns that are applied an aggregate method by the Method Property. The ColumnFilter property has the
following syntax:

ColumnFilter = String;

where String is the filter expression.


Adding a filter row
Use a filter row when you want to filter the query on a field, but you don't want to include the field in the
dataset. For example, you might want to filter a date field on a specific date, but you don't want to include the
date in the dataset. To set up a filter row, first add a filter element that specifies the table field on which you
want to filter, Then, add the ColumnFilter property to set the conditions of the filter.
Example
The following query object links the Customer table and the Sales Line table and retrieves the total quantity of
line items ordered for each customer. The query includes the following filters.
A filter on the Qty column to include only records from the Sales Line table where the total quantity is
less than 50.
A filter on filter row for the Location Code field of the Sales Line table that includes only records where
the location code is WHITE.
query 50100 "Customer_Sales_Quantity"
{
QueryType = Normal;

elements
{
dataitem(C; Customer)
{
column(Customer_Number; "No.")
{
}

column(Customer_Name; Name)
{
}

dataitem(SL; "Sales Line")


{
DataItemLink = "Sell-to Customer No." = c."No.";
SqlJoinType = InnerJoin;
DataItemTableFilter = Quantity = filter(> 10);

column(Qty; Quantity)
{
Method = Sum;
ColumnFilter = Qty = filter(< 50);
}

filter(Location_Code; "Location Code")


{
ColumnFilter = Location_Code = const('White');
}
}
}
}
}

In an SQL SELECT statement, filters on a column or filter row that don't apply an aggregate method, as with the
Location_Code filter row in the example, would correspond to a WHERE clause. Filters on a columns or filter
rows that do apply a totals method, as with the Quantity column in the example, would correspond to a
HAVING clause. For more information, see Equivalent SQL SELECT Statements for Query Filters.

Filtering using SETFILTER and SETRANGE methods


AL code includes the SETFILTER and SETRANGE methods that you can use to apply a filter on a field that is
represented as a column or filter row in a query. The SETFILTER and SETRANGE methods enable you to set
filters programmatically on a query at runtime. You use the SETRANGE method to filter on a range of values in
a column or filter row. The SETFILTER method is more versatile than the SETRANGE method and enables you
to filter a field based on a filter expression.
These methods will overwrite any filter on the same field that is set on a column or filter row by the
ColumnFilter property. If a SETFILTER or SETRANGE method filters on the same field as a filter on a data item,
as specified by the DataItemTableFilter Property, then the method filter and DataItemTableFilter property filter
are combined.
Calling the SETFILTER and SETRANGE methods
You can call the SETFILTER and SETRANGE method from the AL code of the Business Central object that runs
the query object or from the OnBeforeOpen Trigger of the query object.
To call the SETFILTER method, you use the following code.
Query.SetFilter(Column, String)

To call the SETRANGE method, you use the following code.

Query.SetRange(Column, FromValue, ToValue)

where:
Query is a variable of the Query type that specifies the query object.
Column is the name of the column or filter row as defined by its Name property.
String is the filter expression.
FromValue is the lower value of the range.
ToValue is the higher value of the range.

For more information about these methods and important behavior, see SETFILTER method and SETRANGE
method (Query).
Example
Referring to the query example in the previous sections, you can add the following code to the OnBeforeOpen
trigger of the query object to change the filters on the Quantity column and the Location\_Code filter row to
include quantities of in the range of 10 to 50 and a location code of RED.

trigger OnBeforeOpen()
begin
currQuery.SETRANGE(Qty, 10, 50);
currQuery.SETFILTER(Location_Code, '=RED');
end;

Equivalent SQL SELECT Statements for Query Filters


If you're familiar with SQL, then it is helpful to know how filtering in Business Central queries relates to SQL
statements. To specify filters in an SQL statement, you use WHERE and HAVING clauses. The WHERE clause
filters on fields. The HAVING clause filters on the results that have aggregated values as applied by of a totals
method.
The following example shows the corresponding SQL SELECT statement for the previous data item filter
example that links the Customer and Sales Line tables and filters on the Quantity field.

SELECT Customer."No.", Customer.Name, "Sales Line".Quantity


FROM Customer LEFT OUTER JOIN "Sales Line"
ON Customer."No." = "Sales Line".Sell-to Customer No.
WHERE "Sales Line"."Quantity" > 10

The following example shows the corresponding SQL SELECT statement for the previous column and filter row
example that links the Customer and Sales Line tables and filters on the Location Code field and the total sum
of the Quantity field.
SELECT Customer."No.", Customer.Name, SUM("Sales Line".Quantity) as Qty
FROM Customer LEFT OUTER JOIN "Sales Line"
ON Customer."No." = "Sales Line".Sell-to Customer No.
WHERE "Sales Line"."Location Code" = WHITE
GROUP BY Customer."No."
HAVING Qty 50

See Also
Query Object
Aggregating Data
SETFILTER method
SETRANGE method
Aggregating Data in Query Objects
2/6/2023 • 6 minutes to read • Edit Online

In a query object, you can use the Method property to do a calculation on the fields of a column and return the
calculated value in the dataset. For example, you can sum all the fields in a column or find the average value. The
Method property is set on column controls and can be set to any of the following aggregate methods.

A GGREGAT E M ET H O D DESC RIP T IO N

Sum Calculates the sum of the values of the field in the


designated column for all records that are selected as part of
the grouped set.

Average Calculates the average value of the field in the designated


column for all records that are selected as part of the
grouped set.

When averaging fields that have an integer data type (such


as Integer or BigInteger ), integer division is used. The
result isn't rounded, and the remainder is discarded. For
example, 5÷2=2 instead of 2.5 (or 2 1/2).

Min Retrieves the lowest value of the field in the designated


column for all records that are selected as part of the
grouped set.

Max Retrieves the highest value of the field in the designated


column for all records that are selected as part of the
grouped set.

Count Returns the number of records that are selected as part of


the grouped set.

Setting up an aggregate method for a query column


Except for the Count method, you can only use an aggregate method ( Sum , Average , Min , and Max ) on a field
that has a numeric data type of Decimal, Integer, BigInteger, or Duration. To set up an aggregate on a column,
you set the column's Method Property.

column(Name; Field)
{
Method = Sum|Average|Min|Max|Count;
}

Setting an aggregate method on a column will automatically group the resultant data set by the other columns
in the query. Records that have matching values for the other columns are grouped together into a single row in
the results. The aggregate method is then applied against the group and a summary value returned in the row.
It's similar to the GROUP BY clause in SQL SELECT statements (see Creating Queries with Aggregates in SQL).
The aggregate methods and grouping are further explained in the following sections.
Sample Query
The following sample query object retrieves the number of line items in every sales order for each customer.
The query links the Customer table and the Sales Line table. In its current state, the Method property is
commented out so it doesn't implement any aggregate method.

query 50101 "Customer_Sales_Quantity"


{
QueryType = Normal;
// Sorts the results in descending order
OrderBy = descending(Qty);

elements
{
dataitem(C; Customer)
{
column(Customer_Number; "No.")
{
}

column(Customer_Name; Name)
{
}

dataitem(SL; "Sales Line")


{
DataItemLink = "Sell-to Customer No." = c."No.";
SqlJoinType = InnerJoin;

column(Qty; Quantity)
{
// Change the value of the property to perform a different aggregate method on grouped
columns:
// Sum, Average, Max, Min, or Count
// Method = Sum|Average|Min|Max|Count;
}
}
}
}
}

The following table represents a simplified version of the resulting dataset for the sample query.

C USTO M ER_N UM B ER C USTO M ER_N A M E QT Y

20000 Selangorian Ltd. 400

30000 Blanemark Hifi 350

20000 Selangorian Ltd. 300

40000 Deerfield Graphics 250

20000 Selangorian Ltd. 200

30000 Blanemark Hifi 150

The following sections explain how you can modify the query to implement the different aggregate methods by
changing the value of the Method property.
Sum
The Sum method adds the values of all fields for the specified column within a group. To set up a Sum method
on the Quantity column of the sample query, set the Method property to Sum . The query is automatically
grouped by the No. and Name columns.

...
column(Qty; Quantity)
{
Method = Sum;
}
...

Looking at the sample query, you can use Sum method to get the total number of items in sales orders for each
customer. The following table illustrates the resulting dataset for the query.

C USTO M ER_N UM B ER C USTO M ER_N A M E QT Y

20000 Selangorian Ltd. 900

30000 Blanemark Hifi 500

40000 Deerfield Graphics 250

Average
The Average method calculates the average value of the fields in the column within a group. To set up an
Average method on the Quantity column of the sample query, set the Method property to Average . The query
is automatically grouped by the No. and Name columns:

...
column(Qty; Quantity)
{
Method = Average;
}
...

Looking at the sample query, you can use Average method to get the average number of items in sales orders
for each customer. The following table illustrates the resulting dataset for the query.

C USTO M ER_N UM B ER C USTO M ER_N A M E QT Y

20000 Selangorian Ltd. 300

30000 Blanemark Hifi 250

40000 Deerfield Graphics 250

Min
The Min method retrieves the lowest value of fields in the column within a group. To set up a Min method on
the Quantity column of the sample query, set the Method property to Min . The name of the Quantity column
automatically changes to Min_Quantity and the query is automatically grouped by the No. and Name
columns:

...
column(Qty; Quantity)
{
Method = Min;
}
...

Looking at the sample query, you can use Min method to get the least number of items in sales orders for each
customer. The following table illustrates the resulting dataset for the query.

C USTO M ER_N UM B ER C USTO M ER_N A M E QT Y

40000 Deerfield Graphics 250

20000 Selangorian Ltd. 200

30000 Blanemark Hifi 150

Max
The Max method retrieves the highest value of fields in the column within a group. To set up a Max method on
the Quantity column of the sample query, set the Method property to Max . The name of the Quantity column
automatically changes to Max_Quantity and the query is automatically grouped by the No. and Name
columns:

...
column(Qty; Quantity)
{
Method = Max;
}
...

Looking at the sample query, you can use Max method to get the greatest number of items in sales orders for
each customer. The following table illustrates the resulting dataset for the query.

C USTO M ER_N UM B ER C USTO M ER_N A M E QT Y

20000 Selangorian Ltd. 400

30000 Blanemark Hifi 350

40000 Deerfield Graphics 250

Count
The Count method returns the number of records from the data item table that comprise a group in the dataset.
Unlike the other aggregate methods, the Count method is not associated with a specific column. Records are
identified and counted based on the primary key of the data item table. Referring to the sample query, you can
use a Count method to get the number of open sales orders per customer.
To set up a Count method in the sample query, the column element definition cannot include a source table;
only a name. Therefore, you can delete the reference to the Quantity field in the column(Qty; Quantity)
element and set the Method property to Count :

...
column(Qty)
{
Method = Count;
}

Looking at the sample query, you can use Count method the number of sales orders for each customer. The
following table illustrates the resulting dataset for the query.

C USTO M ER_N UM B ER C USTO M ER_N A M E QT Y

20000 Selangorian Ltd. 3

30000 Blanemark Hifi 2

40000 Deerfield Graphics 1

In SQL SELECT statements, the Count method corresponds to a COUNT(*) or COUNT(field) clause.

Creating queries with aggregates in SQL


If you're familiar with SQL, then it's helpful to know how the aggregate methods in Business Central relate to
SQL statements. To specify an aggregate method in an SQL statement, you add the method to the SELECT
statement and then add a GROUP BY clause.
The following example shows how to use an SQL statement to create an inner join of the Customer table and
Sales Line table, and a sum of items for each customer. The result is grouped by the No. and Name columns.

SELECT Customer."No.", Customer.Name, SUM("Sales Line".Quantity)


FROM Customer INNER JOIN "Sales Line"
ON Customer."No." = "Sales Line"."Sell-to Customer No."
GROUP BY Customer."No.", Customer.Name

See Also
Method Property
Query Object
Filtering Queries
Aggregating Data
Aggregate Functions (Transact-SQL)
Retrieving Date Data in Queries
2/6/2023 • 4 minutes to read • Edit Online

When you have fields in a table that contain dates, you can use a date method to retrieve only the year, month,
or day instead of including the date in the resulting dataset of a query.

Setting up a Date method on a query column


To set up a date method on a query column, set the Method Property to Day , Month , and Year .

IMPORTANT
You can only use a date method on fields that have a Date or DateTime data type. For additional information about how
to use a date method on a field that has the DateTime data type, see Working with DateTime Data Types.

For more information about how to set up query columns and properties, see Query Object.

Sample table and query


This article uses the following sample table and query to demonstrate the different date methods.
Sample Sales Header table
The following table contains data about sales orders for customers. The Order Date field has the data type of
Date and the format DD-MM-YYYY, where DD is the day, MM is the month, and YYYY is the year.

N O. B IL L - TO N A M E O RDER DAT E

1000 Autohaus Meilberg KG 18-01-2019

5000 Autohaus Meilberg KG 21-05-2019

4000 Beef House 30-09-2017

3000 Deerfield Graphics Company 05-04-2018

3000 Deerfield Graphics Company 29-04-2018

NOTE
This is a simplified subset of the data that is found in table 36 Sales Header of the CRONUS International Ltd.
demonstration database.

Sample query
The following query object retrieves data from the sample Sales Header table. The query includes a totals
method that counts the total the number of records from the table included in the dataset.
query 50100 "Sample Data Query"
{
QueryType = Normal;

elements
{
dataitem(Sales_Header; "Sales Header")
{
column(Bill_to_Name; "Bill-to Name")
{
}

column(Order_Date; "Order Date")


{
// Change the value of the property to Day, Month, or Year
Method = Day;
}

column(Count_)
{
Method = Count;
}
}
}
}

NOTE
A column that applies a date method is still part of the group unlike columns that apply an aggregate method.

Day method
The Day method retrieves the day from the date expression of a field value in the query column. The day is
returned as an integer, in the range of 1 to 31, which represents the day of the month. If the day in the date
expression is 0, then 1 is returned.
Example
The following table displays the resulting dataset for the sample query with the Method property of the
Order Date column set to Day .

B IL L _TO _N A M E DAY _O RDER_DAT E C O UN T _

Autohaus Meilberg KG 18 1

Autohaus Meilberg KG 21 1

Beef House 30 1

Deerfield Graphics Company 5 1

Deerfield Graphics Company 29 1

Month method
The Month method retrieves the month from the date expression of a field value in the query column. The
month is returned as an integer, in the range of 1 to 12, where 1 represents January and 12 represents
December. If the month in the date expression is 0, then 1 is returned.
Example
The following table displays the resulting dataset for the sample query with the Method property of the
Order Date column set to Month .

B IL L _TO _N A M E M O N T H _O RDER_DAT E C O UN T _

Autohaus Meilberg KG 1 1

Autohaus Meilberg KG 5 1

Beef House 9 1

Deerfield Graphics Company 4 2

Year method
The Year method gets the year from the date expression of a field value in the query column. The year is
returned as an integer. If the year in the date expression is 0, then 1900 is returned.
Example
The following table displays the resulting dataset for the sample query with the Method property of the
Order Date column set to Year

C USTO M ER N A M E Y EA R_O RDER_DAT E C O UN T _

Autohaus Meilberg KG 2019 2

Beef House 2017 1

Deerfield Graphics Company 2018 2

Working with DateTime Data Types


On the SQL server, date and time values are processed using Coordinated Universal Time (UTC). If your Business
Central solution uses a time zone other than UTC and the field on which you apply the date method has a data
type of DateTime, then there might be a difference between the date value that is returned in the dataset for the
field and the actual day, month, or year for the field in the table. This occurs when the corresponding UTC date
for a field falls on the next day or previous day because of the time of day and the time zone of Business Central
solution. The following table includes examples of DateTime values for two time zones that will return days,
months, and years in a dataset that differ from the values in the table.

DAT E A N D T IM E IN DAY RET URN ED B Y M O N T H RET URN ED Y EA R RET URN ED B Y


T IM E Z O N E B USIN ESS C EN T RA L DAY M ET H O D B Y M O N T H M ET H O D Y EA R M ET H O D

Pacific Time (UTC – 12-31-2011 31 12 2018


8:00:00) 17:00:00

Middle European 01-01-2012 1 1 2019


Time (UTC +1:00:00) 00:59:00

The differences in day, month, or year occur because when a date and time value is retrieved from the Business
Central database table, it is converted from the regional settings of the Business Central solution to the UTC date
and time. The day, month, or year is calculated on the SQL server, and then returned to the query dataset as an
integer, which does not consider the regional settings of the Business Central solution.
To avoid this condition, you should use the date method on fields that have a Date data type instead of a
DateTime data type whenever possible. You can also return the DateTime value and implement post processing
for the day, month, and year as needed.

See Also
Query Objects
Aggregating Data in Query Objects
Method Property
Using Queries Instead of Record Variables
2/6/2023 • 2 minutes to read • Edit Online

In scenarios where you want to read records from multiple tables, it can be a good idea to use a query instead of
implementing code with record variables. Using a query can improve performance and also simplify the AL
code that is required to perform the operation.

Code Example Using Record Variables


The following AL code shows an example of using record variables to retrieve and handle records from two
tables. You could potentially use this code to track item movement. The code uses two record variables, Item
and ItemLedgerEntry , to retrieve the first five records from table 27 Item and table 32 Item Ledger Entr y
where the Entr y Type field equals Sale . The retrieved records are passed to and handled by the OutputData
method.

begin
count := 0;
if Item.FINDSET then
repeat
PrevDate := 0D;
TotalQty := 0;
ItemLedgerEntry.SETCURRENTKEY("Item No.", "Posting Date");
ItemLedgerEntry.SETRANGE("Item No.", Item."No.");
ItemLedgerEntry.SETRANGE("Entry Type",
ItemLedgerEntry."Entry Type"::Sale);
if ItemLedgerEntry.FINDSET then
repeat
if (ItemLedgerEntry."Posting Date" <> PrevDate) and (PrevDate <> 0D) then begin
OutputData(1, Item."No.", Item.Description, PrevDate, -TotalQty);
TotalQty := 0;
count := count + 1;
end;
PrevDate := ItemLedgerEntry."Posting Date";
TotalQty := TotalQty + ItemLedgerEntry.Quantity;
until (ItemLedgerEntry.NEXT = 0) or (count >= 4);
if PrevDate <> 0D then begin
OutputData(1, Item."No.", Item.Description, PrevDate, -TotalQty);
count := count + 1;
end;
until (Item.NEXT = 0) or (count >= 4);
end;

Corresponding Query Implementation


The following AL code represents a query object and additional code that will return the same results as the
previous example that uses record variables.
query 50100 "Item Movements Query"
{
QueryType = Normal;

elements
{
// This dataitem corresponds to the `Item` record variable in the record variable example.
dataitem(Item; Item)
{
column(No_; "No.")
{
}
column(Description; Description)
{
}

// This dataitem corresponds to the `ItemLedgerEntry` record variable in the record variable
example.
dataitem(Item_Ledger_Entry; "Item Ledger Entry")
{
// The DataItemLink and SqlJoinType settings correspond to the
`ItemLedgerEntry.SETRANGE("Item No.",Item."No.");` statement in the record variable example.
DataItemLink = "Item No." = Item."No.";
SqlJoinType = InnerJoin;

filter(Entry_Type; "Entry Type")


{
}
column(Posting_Date; "Posting Date")
{
}

// The SUM corresponds to the `TotalQty := TotalQty + ItemLedgerEntry.Quantity;` statement


in the record variable example.
column(Sum_Quantity; Quantity)
{
Method = Sum;
}
}
}
}
}

Add the following code to a codeunit that will run the query.

var
ItemMovements: Query "Item Movements"
begin
ItemMovements.TopNumberOfRows(5);
ItemMovements.SetRange(Entry_Type,ItemMovements.Entry_Type::Sale);
ItemMovements.Open;
while ItemMovements.Read do
OutputData(2,
ItemMovements.Item_No,ItemMovements.Description,ItemMovements.Posting_Date,ItemMovements.Sum_Quantity);
end;

The ItemMovements.TOPNUMBEROFROWS(5); statement will include only the first 5 records in the resulting dataset
and corresponds to implementing the count variable in the record-based code example.
The OutputData method performs the same operations as the OutputData method in the record variable
example.

See Also
Query Object
Linking and Joining Data Items
Aggregating Data in Query Objects
Filtering Data in Query Objects
SETRANGE Method
OPEN Method
TOPNUMBEROFROWS Method
API Query Type
Developing Extensions
AL Development Environment
Accessing Columns of a Query Dataset
2/6/2023 • 2 minutes to read • Edit Online

If the query is in the reading state, you can retrieve the value of columns in the current active row of the dataset
by using the following syntax in AL.

Syntax
ColumnValue := QueryVariable.ColumnName

QueryVariable is a variable of the Query data type that specifies the query object.
ColumnName is the name of the column in the query object.

Return Value
The data type of the field that is used by the column, unless the column applies a totaling method as specified by
the Method Property. If the column applies a totaling method, then data type is an integer for the Count
method and a decimal for all other totaling methods.
Returns the value of the column in the current active row.

Remarks
A column of a row can only be accessed after the query has been opened by using a call to the Open Method
followed by a call to the Read Method. The current active row is the row that has been included in the query
variable after the last call to Read Method.

Example
This example demonstrates how to access a column of a query dataset. When the query is run, each row in the
dataset is read and message box is displayed that contains the value of a column in the row.
The following query object links table 18 Customer and table 37 Sales Line .
query 50123 "Customer_Sales_Quantity"
{
QueryType = Normal;
// Sets the results to only include the top forts the results in descending order
TopNumberOfRows = 5;
OrderBy = descending(Qty);

elements
{
dataitem(C; Customer)
{
column(Customer_Number; "No.")
{
}

column(Customer_Name; Name)
{
}

dataitem(SL; "Sales Line")


{
DataItemLink = "Sell-to Customer No." = c."No.";
SqlJoinType = InnerJoin;

column(Qty; Quantity)
{
}
}
}
}
}

The following codeunit opens the query, reads each row of dataset, and then displays a message that has the
content of each row.

codeunit 50100 QueryColumnAccess


{
trigger OnRun()
begin

// Sets a filter to display only sales quantities greater than 20.


MyQuery.SETFILTER(Qty, '>20');
// Runs the query.
MyQuery.OPEN;
// Reads each row in the dataset and displays a message with column values.
// Stops reading when there are no more rows remaining in the dataset (READ is FALSE).
while MyQuery.READ do begin
MESSAGE(Text000, MyQuery.Customer_Name, MyQuery.Qty);
end;
// Closes the query.
MyQuery.CLOSE;

end;

var
MyQuery: Query "Customer_Sales_Quantity";

Text000: Label 'Customer name = %1, Quantity = %2.';


}

See Also
Query Object
Filtering Queries
Aggregating Data
Transferring Data Between Tables using
DataTransfer
2/6/2023 • 5 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 2 (version 21.0) and later.

DataTransfer is an AL data type that supports the bulk transferring of data between SQL based tables. Instead of
operating on a row-by-row model, like the record API does, DataTransfer produces SQL code that operates on
sets. This behavior improves the performance when moving data during upgrade.
For comparison, the following code illustrates how to copy rows using the record API:

local procedure CopyRows()


var
from: Record FromTable;
to: Record ToTable;
begin
if from.Find() then
repeat
to.SmallCodeField := from.SmallCodeField;
to.IntField := from.IntField;
to.id := from.id;
to.Insert();
until from.Next() = 0;
end;

The same can be done using DataTransfer:

local procedure CopyRows()


var
dt: DataTransfer;
to: Record ToTable;
begin
dt.SetTables(Database::FromTable, Database::ToTable);
dt.AddFieldValue(2, to.FieldNo("SmallCodeField"));
dt.AddFieldValue(3, to.FieldNo("IntField"));
dt.AddFieldValue(1, to.FieldNo("id"));
dt.CopyRows();
end;

Usage and behavior


The DataTransfer object can be used for essentially two operations:
Copy data from one or more fields in a table to fields another table. A typical scenario is when you've made a
field obsolete.
Copy data from entire rows in a table to rows in another table. A typical scenario is when you've made a table
obsolete.
IMPORTANT
The DataTransfer object can only be used in upgrade code and it will throw an runtime error if used outside of upgrade
codeunits.

The DataTransfer object can't be used on the following tables:


Non-SQL tables
System tables
Virtual tables
Audited tables as the destination
Obsoleted tables as the destination

Design guideline
DataTransfer uses a builder design pattern that, in general, requires that you complete the following steps:
1. Specify the source and destination tables by calling the SetTables.
2. Specify which fields to transfer or constant values by calling the AddFieldValue. Or you can set a constant
value for fields in the destination using AddConstantValue, respectively.
3. Define the relationship between the source and destination tables by calling AddJoin. In most cases, this
method is required for copying fields.
4. Add constraints on the data to transfer by calling AddSourceFilter.
5. Invoke the query for transferring data by calling CopyFields or CopyRows.
Because DataTransfer operates in bulk and not on a row-by-row basis, row based events or triggers won't be
executed. For example, when calling CopyFields, none of the following events will be called: OnBeforeModify,
OnModify, or OnAfterModify. Or, when calling CopyRows, none of the following events will be called:
OnBeforeInsert, OnInsert, or OnAfterInsert.

Copy fields
Calling CopyFields on the DataTransfer object will copy selected fields from one table (the source) to another
table (the destination). Unless you're copying with the same source and destination table, specifying a join
condition is necessary. The join condition specifies how to match rows from the source with rows from the
destination table.
Example 1
A typical scenario is obsoleting a field and moving its data into another table. For example, suppose you have
two tables, Source and Destination , as illustrated with sample data below. You're planning on obsoleting field
S3 in the Source table. But before you do, you want to copy some values of S3 into the field D3 of the
Destination table. Specifically, you only want to copy field S3 in rows where field S2 is equal to A.

SO URC E TA B L E DEST IN AT IO N TA B L E ( B EF O RE C O P Y ) DEST IN AT IO N TA B L E ( A F T ER C O P Y )


PK S1 S2 S3 PK D1 D2 D3 PK D1 D2 D3

1 A A 42 1 A A 99 1 A A 42

2 B A 43 2 B A 2 B A 43

3 C B 44 4 C B 4 C B

4 D B 45

The code to accomplish this operation is as follows.

local procedure CopyFields()


var
dt: DataTransfer;
dest: Record Destination;
src: Record Source;
begin
dt.SetTables(Database::Source, Database::Destination);
dt.AddFieldValue(src.FieldNo("S3"), dest.FieldNo("D3"));
dt.AddSourceFilter(src.FieldNo("S2"), '=%1', 'A');
dt.AddJoin(src.FieldNo("PK"), dest.FieldNo("PK"));
dt.CopyFields();
end;

Performance
The same scenario could also be coded using the record API, by first looping over all rows in the Source table
with a filter on field S2 , then for each match, calling Get on the destination record, setting the fields, and calling
Modify.
The record-based solution executes three SQL operations per-row, while the DataTransfer does a maximum of
two SQL queries altogether. Measurements for DataTransfer and record API solutions have shown an ~200x
performance improvement for DataTransfer. Gains are even greater if the destination table has modify triggers
or if the environment has significant latency to SQL.
Uniqueness in the source table
The join condition can be specified on arbitrary fields, which leaves the possibility that the set of fields doesn't
produce a unique set of rows on that set of fields. This situation would lead to a many-to-many relation between
the tables. A many-to-many relation would require the runtime to know which row to select—which at best
would be selected at random. Instead, the upgrade runtime will detect this situation and throw an error. The
following table illustrates an example where joining the fields S1 and S2 doesn't produce a unique set of rows,
and would therefore lead to a runtime error.

PK S1 S2 S3

1 A A 42

2 A A 43

3 C B 44

4 D B 45
Copy rows
Calling CopyRows on the DataTransfer object inserts a row in the destination table for each matching row in the
source table. Fields in the inserted row are populated with values specified by calling AddFieldValue or
AddConstantField. Fields not specified by AddFieldValue or AddConstantField are populated with the field's
InitValue or the field's default value.
If the code tries to copy a row from the source table that has the same primary key as an existing row in the
destination table, a runtime error will be thrown.
Example 2
To help explain CopyRows, consider an example using sample tables Source and Destination again.

SO URC E TA B L E DEST IN AT IO N TA B L E ( B EF O RE C O P Y ) DEST IN AT IO N TA B L E ( A F T ER C O P Y )

PK S1 S2 S3 PK D1 D2 D3 PK D1 D2 D3

2 B A 43 1 A A 99 1 A A 99

3 C A 44 2 X 43

4 D B 45 3 X 44

In this code example, you copy the PK and S3 fields for all rows where S2 equals A and add them as new rows
in the Destination table. You use AddConstantValue method to give the field D2 the value X in the inserted
rows.

local procedure CopyRows()


var
dt: DataTransfer;
src: Record Source;
dest: Record Destination;
begin
dt.SetTables(Database::Source, Database::Destination);
dt.AddFieldValue(src.FieldNo("PK"), dest.FieldNo("PK"));
dt.AddFieldValue(src.FieldNo("S3"), dest.FieldNo("D3"));
dt.AddConstantValue('X', dest.FieldNo("D2"));
dt.AddSourceFilter(src.FieldNo("S2"), '=%1', 'A');
dt.CopyRows();
end;

Performance
As with CopyFields, CopyRows is a bulk operation. It provides performant execution by doing only a single SQL
statement for the entire operation, instead of doing multiple per-row operations. Measurements have shown an
~50x performance improvement with a DataTransfer solution compared with a record API solution.

See Also
Upgrading Extensions
XMLport Overview
2/6/2023 • 2 minutes to read • Edit Online

An XMLport is composed of the following items:


An XMLport object
An XMLport schema
A Request page
Properties, triggers, and code

XMLport object
You create an XMLport object in the AL Language development environment to define the schema of an XML
document. You can export and import data between an external source and Dynamics 365 Business Central with
XMLports. For more information, see XMLport Object.
XMLport schema
In order to define the underlying structure of the imported or exported document, you use the XMLport schema.
An XMLport schema determines which data is exported from or imported to Dynamics 365 Business Central
database tables and the format and structure of the files used. You build the XMLport schema by adding nodes.
For more information, see Defining a XMLport Schema.

Request page
Request pages are dialog boxes that enable the user to set a filter on the data, sort the data, or choose whether
to export or import the data. For more information, see Request Pages.
Unlike report request pages, XMLport request pages cannot be bookmarked by users from the user interface.

XMLport properties, triggers, and code


XMLport objects include triggers, methods, and properties that can be used to work with the object. For more
information, see XMLport Data Type and XMLport Triggers.
When you design XMLports, you must set the value of the Format Property (XMLports) and the Direction
Property. The Format Property (XMLports) indicates the type of file that you want to import or export and the
Direction Property value indicates whether the XMLport will be used for import or export.
For more information about data consistency and validation against possible errors when using XMLports, see
the blog post Importing and exporting valid data using XMLports in Dynamics 365 Business Central.

See Also
XMLport Object
Defining a XMLport Schema
Using Namespaces with XMLports
Request Pages
XMLport Data Type
XMLport Triggers
XMLport Object
2/6/2023 • 2 minutes to read • Edit Online

XMLports are used to export and import data between an external source and Dynamics 365 Business Central.
Sharing data between different computer systems is seamless when it is shared in an XML format. Working with
XML files can be tedious so the details of how the XML file is handled are encapsulated in XMLports.
To use an XMLport to import or export data, you first create an XMLport object. Once created, you can run the
XMLport from a page or codeunit object.
You can design XMLports to include a request page, which is a dialog box that enables the user to set a filter on
the data, sort the data, or choose whether to export or import the data. For more information about request
pages, see Request Pages.

XMLport example
The following example shows a page extension of the Permission Sets page that adds an action to the
specified page calling the XMLport Expor tPermissionSet . The XMLport exports the permission set data to an
XML file.

pageextension 50111 PermissionSetExporter extends "Permission Sets"


{
actions
{
addafter(Permissions)
{
action(ExportPermissionSet)
{
Promoted = true;
PromotedCategory = New;
trigger OnAction();
begin
Xmlport.Run(50112, false, false);
end;
}
}
}
}

xmlport 50112 ExportPermissionSet


{
Format = xml;

schema
{
textelement(PermissionSets)
{
tableElement(PSet; "Aggregate Permission Set")
{
SourceTableView = WHERE ("App Name" = FILTER (<> ''));
XmlName = 'PermissionSet';
fieldattribute(RoleID; pset."Role ID") { }
fieldattribute(RoleName; pset.Name) { }
tableelement(P; "Tenant Permission")
{
XmlName = 'Permission';
LinkTable = pset;
LinkFields = "Role ID" = FIELD ("Role ID");
textelement(ObjectType)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Object Type";
ObjectType := format(int);
end;
}
textelement(ObjectID)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Object ID";
ObjectID := format(int);
end;
}
textelement(ReadPermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Read Permission";
ReadPermission := format(int);
end;
}
textelement(InsertPermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Insert Permission";
InsertPermission := format(int);
end;
}
textelement(ModifyPermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Modify Permission";
ModifyPermission := format(int);
end;
}
textelement(DeletePermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Delete Permission";
DeletePermission := format(int);
end;
}
textelement(ExecutePermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Execute Permission";
ExecutePermission := format(int);
end;
end;
}
textelement(SecurityFilter)
{
trigger onbeforePassvariable();
begin
SecurityFilter := format(p."Security Filter");
end;
}
}
}
}
}
}

See Also
Developing Extensions
AL Development Environment
XMLport Overview
Using Namespaces with XMLports
Page Extension Object
Report Object
Defining an XMLport schema
2/6/2023 • 2 minutes to read • Edit Online

You use an XMLport object to export and import data between an external source and Dynamics 365 Business
Central. The schema determines which and how data is extracted from or inserted into the Dynamics 365
Business Central database tables through an XMLport. For more information, see XMLport Object.
You build the XMLport schema from nodes. A node can be:
A text element
A text attribute
A table element
A field element
A field attribute
You nest nodes inside other nodes in order to define the structure of the XMLport schema. Use the following
keywords to define the structure.

K EY W O RD DESC RIP T IO N

textelement Defines a new text element in the XMLport. It is used for


XML elements that do not map to a database item or when
the database does not need the information.

textattribute Defines a new text attribute in the XMLport. It is used for


XML attributes that do not map to a database item or when
the database does not need the information.

tableelement Defines a new table element in the XMLport. It is used for


XML elements that map to a table in the database, which is
specified in the SourceTable Property. When the XMLport is
run, the code nested inside the table element is iterated for
all records in the underlying table.

fieldelement Defines a new field element in the XMLport. It is used for


XMLport elements that map to a field in the database, which
is specified in the SourceField Property. You must specify it
inside the parent table element of the field.

fieldattribute Defines a new field attribute in the XMLport. It is used for


XMLport attributes that map to a field in the database,
which is specified in the SourceField Property.

NOTE
There can only be one <root> node, which must be an element. If the Format Property is set to Xml, it must be a
textelement node.

There can be several attributes for a single element and their order does not matter. Attribute nodes must be
specified inside the element nodes they refer to and before other element nodes. They cannot have nested
element nodes.

Snippet support
Typing the shortcut txmlport will create the basic layout for an XMLport object when using the AL Language
extension in Visual Studio Code.
Example
The following example adds the Customer table as a table element, the Address field as a field element and the
County and City fields as field attributes.

schema
{
textelement(Customers)
{
tableelement(Customer; Customer)
{
fieldelement(Address; Customer.Address)
{
fieldattribute(County; Customer.County){}
fieldattribute(City; Customer.City){}
}
}
}
}

For more information about designing XMLports, see XMLport Overview.


For more information about data consistency and validation against possible errors when using XMLports, see
the blog post Importing and exporting valid data using XMLports in Dynamics 365 Business Central.
For information about the use of namespaces in XMLports see Using Namespaces with XMLports.

See Also
XMLport Object
XMLport Data Type
Using Namespaces with XMLports
XMLport Triggers Request Pages
XMLport Overview
Using Namespaces with XMLports
2/6/2023 • 2 minutes to read • Edit Online

The external system that provides or consumes AL Language development environment data as XML might
require that the XML documents include namespaces. Namespaces are used to avoid element name conflicts. In
these cases, you must add namespaces on the XMLport to make it compatible with the XML schema that is used
by the external system.

NOTE
Namespace-related properties are only available when the Format Property is set to Xml.

For example, the following code is a portion of a simple XML document for transferring sales order information.
The XML includes namespaces for mapping fields from the Sales Header table.

<?xml version="1.0" encoding="UTF-16"?>


<Root xmlns="urn:bc:schema:all" xmlns:bcField="urn:bc:schema:field" xmlns:bcTable="urn:bc:schema:table">
<bcTable:SalesHeader>
<bcField:DocType>Order</bcField:DocType>
<bcField:DocNo>101005</bcField:DocNo>
<bcField:SellToCustNo>30000</bcField:SellToCustNo>
<bcField:SellToCustName>John Haddock Insurance Co.</bcField:SellToCustName>
<bcField:BillToCustNo>30000</bcField:BillToCustNo>
<bcField:BillToCustName>John Haddock Insurance Co.</bcField:BillToCustName>
</bcTable:SalesHeader>
...
</Root>

Each namespace has the syntax xmlns:prefix="namespacename".


The namespacename is a string of characters, often referred to as a Uniform Resource Identifier (URI),
which uniquely identifies an Internet resource. This is typically a Uniform Resource Locator (URL) or
Universal Resource Name (URN).
The prefix is a short string of characters that acts as an alias for the namespace name. The prefix is
applied to specific elements in the XML document. The example includes the prefixes bcField and
bcTable .

A namespace that does not include a prefix declares the default namespace. In the example, the default
namespace is urn:bc:schema:all. The default prefix is applied to all the elements that do not include a
prefix.
You declare the namespaces used in the XMLport using the Namespaces Property. For each namespace, you
specify a prefix and a namespace name. You can declare a default namespace by defining an empty prefix "" . In
the XML documents exported or imported by the XMLport, the namespaces declarations are only supported in
the <root> element.
You then apply the namespaces to XMLport elements by setting the NamespacePrefix Property of the element
to one of the namespace prefixes declared in the Namespaces Property. This property only applies to
textelement , tableelement and fieldelement nodes, otherwise it will be ignored.

You can also specify a default namespace using the DefaultNamespace Property and setting the
UseDefaultNamespace Property to true . Note that there can only be one default namespace, so if you specify
the default namespace in the Namespaces Property, you must set the DefaultNamespace Property to false .

See Also
XMLport Object
Namespaces Property
NamespacePrefix Property
DefaultNamespace Property
UseDefaultNamespace Property
Request Pages
2/6/2023 • 4 minutes to read • Edit Online

A request page is a page that is run before the report or XMLport starts to execute. Request pages enable end
users to specify options and filters for a report and an XMLport. Request pages are defined as part of designing
a Report object, a Report Extension Object, or an XMLport object. The syntax is shown further down in this
article. You design the filters on request pages by using the following report and XMLport properties:

P RO P ERT Y DESC RIP T IO N

RequestFilterHeading Property Sets a caption for the request page tab that is related to a
report's data item or an XMLport's table element.

RequestFilterHeadingML Property Sets the text used as a RequestFilterHeading Property for a


request page tab.

RequestFilterFields Property Specifies which columns are automatically included on the


tab of the request page that is related to a report's data
item or an XMLport's table element. The user can set filters
on these columns.

NOTE
Request pages for XMLports are not supported by the Business Central Web client in versions prior to Dynamics 365
Business Central 2019 release wave 2. If you try to run an XMLport with a Request page from the web client in these
versions, you receive an error that the XMLport page type is not supported. Alternatively, XMLport request pages do
work in the Dynamics NAV Client connected to Business Central.

By default, a request page is displayed, unless the UseRequestPage is set to false ; then the report or XMLport
will start to print as soon as it's run. In this case, end users can't cancel the report or XMLport run. It's still
possible to cancel the report or XMLport, but some pages may print.
By default, without having set anything else, a request page will always display the following buttons:
Send to
Print
Preview
Cancel
Additionally, you can add more options on the request page to allow the end user to filter the data displayed.

Filtering on request pages


The columns that you define as RequestFilterFields are shown on the request page and can be used for
filtering the data before viewing or printing the report.

NOTE
Only on the Windows client, filtering is possible even if RequestFilterFields is not set.
Defining the RequestFilterFields property in the dataitem() part of the report code is done as illustrated in
the following code example:

report 50103 "Customer List"


{
CaptionML = ENU = 'Customer List';
RDLCLayout = 'Customer List Report.rdl'; // if Word use WordLayout property
dataset
{
dataitem(Customer; Customer)
{
RequestFilterFields = "No.", "Search Name", "Customer Posting Group";
...

NOTE
It is recommended to add columns that the end-users of the report will frequently set filters on.

For more information about the report object, see Report Object.
Defining the RequestFilterFields property in the tableelement() part of an XMLport is done in a similar way:

XMLport 50104 "Export Customer List"


{
CaptionML = ENU = 'Export customer List';
Direction = Export;
schema
{
textelement(root)
{
XmlName = 'Root';
tableelement(Customer; Customer)
{
RequestFilterFields = "No.", "Search Name", "Customer Posting Group";
...

For more information about the XMLport object, see XMLport Object.
By default, for every data item in the report and table element in a XMLport, a FastTab for defining filters and
sorting is created on the request page. To remove a FastTab from a request page, don't define any
RequestFilterFields for the data item or table element and set the DataItemTableView property in a report or
the SourceTableView property in an XMLport to define sorting. The request page is displayed, but there's no tab
for this data item or table element.
If a DataItemTableView or SourceTableView isn't defined, then end-users can select a sort column and sort order
at runtime.
In a complex report or XMLport that uses data from several tables, the functionality may depend on a specific
key and sort order. Design your reports and XMLports so that end-users can't change the sort order in a way
that affects their functionality.
For data items and table elements whose source table contains calculated fields, such as amounts and quantities,
the Filter totals by: section is automatically included on the request page, which allows you to adjust various
dimensions that influence calculations.
TIP
For information about how to enter filter criteria on the request page, see Filtering in the Business Central application
help.

Defining a requestpage section


On reports, in addition to defining the filter options by setting the RequestFilterFields property, you can add a
requestpage section. In this section, you can set the SaveValues property to true in order to save the values
that the end user enters on the request page. When the report is run again, the end user will have the option to
use previously defined filters. You can also add a layout to the request page, specifying an Options section to
perform checks.

NOTE
You can use the SaveValues property together with the AllowScheduling property to set up the request page to
support multiple previews. When both properties are true , users can preview the report from the request page as
many times as the like, without having the request page close. This capability lets users change filters, see what the
generated report will look like, and then try again. If either property is set to false , the report won't support multiple
previews and the request page closes once the user previews the report. In this case, the request page includes a
Preview and Close button instead of Preview .

...
requestpage
{
SaveValues = true;

layout
{
area(content)
{
group(Options)
{
Caption = 'Options';
field(PostingDate; PostingDateReq)
{
ApplicationArea = Basic, Suite;
Caption = 'Posting Date';
ToolTip = 'Specifies the posting date for the invoice(s) that the batch job creates.
This field must be filled in.';
}
}
}
}

trigger OnOpenPage()
begin
if PostingDateReq = 0D then
PostingDateReq := WorkDate;
end;

var
PostingDateReq: Date;
}
...

See Also
Report Object
Report Extension Object
XMLport Object
Reports Overview
Report Design Overview
RunRequestPage Method
RequestFilterHeading Property
RequestFilterHeadingML Property
RequestFilterFields Property
DataItemTableView
Customizing the User Interface for User Roles
2/6/2023 • 2 minutes to read • Edit Online

The strength of Business Central is its role-tailored experience that helps users focus on the work that is
important to them. Business Central offers several features for developers, application administrators, and end-
users, that can be used to customize the the pages that users work with in the client. These features customize
the pages on different layers, as illustrated in the following figure. Some customization is done in AL extensions,
while others can be done from the client.

Role Centers
The Role Center is first layer of customization. The Role Center is the user's entry point and home page for
Business Central, displaying information that is pertinent to the user's role in the company and enabling them to
easily navigate to relevant pages for viewing data and performing tasks. You can develop several different Role
Centers, where each Role Center is customized to the profile of the intended users.
A Role Center is created in AL by the rolecenter page type.
For more information, see Designing Role Centers.

Page extensions and designer


A page extension object extends a page object by adding, moving or hiding UI elements that are defined in the
page's source code. Page extensions can be created in Visual Studio Code or from the client using Designer.
Changes made by page extensions affect the UI for all users, regardless of which profile they belong to.

Profiles and page customizations


A profile is the mechanism that makes a Role Center and its associated pages available to users in the client and
enables you to build an individual experience for the specific user role. In the client, profiles are referred to as
Roles . Users sign in to the client under a specific role, which they can switch from the My Settings page.
Different profiles can use the same Role Center. Profiles can be created as part of an extension by writing AL
code or they can be created from the client by a user who has the proper permissions, typically an administrator
or consultant.
On top of the profile are page customizations. Page customizations modify the layout of elements on specific
pages. For example, you can move or hide actions, fields, columns on list, or entire parts; exactly the same
modifications that can be done using personalization. The page customizations will be seen by all users of the
profile. Like profiles, page customizations can be made in AL as part of an extension or from the client by
modifying the profile. Customizations that are made from the client will take precedence over the
customizations in AL.
For more information about profiles and page customization in AL, see Designing Profiles. For information
about using the client, Customizing the Workspace for Profiles (Roles) in the Business Central Application Help.

Personalization
The last layer of customization is personalization. This is done strictly in the client by end-users for customizing
their own workspaces. The changes that users make take precedent over page customizations made on the
profile. The changes will only be seen by the user; not other users. For more information, see Personalizing Your
Workspace in the Business Central Application Help.

See Also
Developing Extensions
AL Development Environment
Page Object
Page Extension Object
Page Extension Properties
Inspecting and Troubleshooting Pages
2/6/2023 • 6 minutes to read • Edit Online

The Business Central Web client includes a page inspection feature that lets you get details about a page. Page
inspection provides insight into the page design, the different elements that form the page, and the source
behind the data it displays. Page inspection helps you:
Learn the data model behind a page.
Discover pages and parts that can be reused in your application design.
Troubleshoot data issues without having to do tasks like copying the production database, viewing the entire
source table, or digging into SQL.
Debug the application, complementing Designer.

Working with Page Inspection


You start page inspection from the Help & Suppor t page. Choose the question mark in the top-right corner,
choose Help & Suppor t , and then choose Inspect pages and data . Or, you can just use the keyboard
shortcut Ctrl+Alt+F1 .
The Page inspection pane opens on the side. The following figure illustrates the Page Inspection pane on the
Sales Order page.

When the Page Inspection pane first opens, it shows information that pertains to the main page object.
Use the keyboard or pointing device to move focus to different elements on the page. When you select a FactBox
or a part on the main page, a border will highlight the area. The Page Inspection pane then shows information
about the selected element. For example, the previous figure shows information about the list part in the Sales
Order page.
As you navigate to other pages in the application, the Page Inspection pane will automatically update with
page information as you move along.
What Page Inspection Shows
The page inspection pane shows the information for the main page or page part, including:
The page's source table (if any) and fields.
Extensions that affect the page.
Current filters applied to the page.
The following sections describe details about what is shown.

NOTE
If you do not see all details described below, you might not have the required permissions. For more information, see
Controlling Access to Page Inspection Details.

TIP
To copy the values of a field or entity under one of the tabs to the clip board, select the field or entity and press Ctrl+C.

Page
Table
Table Fields
Extensions
Page Filters

The Page field shows information about the main page or a selected (highlighted) subpage in a part. The field
shows the following information:
The name, as specified by its Name property
The ID as specified by the ID property.
The type, as specified by the PageType property.
Elements shown with limited information
Role Center pages
If a page has the type Role Center, the Table field doesn't appear. Because the Role Center consists of
several parts, there's no more information shown. To see more details, select the different parts that make
up the Role Center.
Report request pages and previews
If you open a report request page or preview for inspection, the only information shown in the Page
Inspection pane is the report's name and ID.

TIP
From the Business Central client, you can export report results as raw data to a Microsoft Excel file. The file
contains all columns of the dataset, but without the layout applied. Use the file to help validate that the report
returns the expected data, and to ensure that the report layout controls match the dataset value types. To export
a report, run the report and select the Send to > Microsoft Excel Document (data only) on the request
page. For more information, see Working with Reports - Send to Excel.

System parts, such as Links or Notes, and parts containing charts.


See Also
AL Development Environment
Page Extension Object
Actions Overview
Adding Pages and Reports to Search
Personalizing Your Workspace
Using Designer
Designing Role Centers
2/6/2023 • 10 minutes to read • Edit Online

The strength of Dynamics 365 is its role-tailored experience that helps users focus on the work that is important
to them. The Role Center is an integral part of the role-tailored experience. And as a developer, role-tailoring
should be the foundation for your Role Center design.

About the Role Center


The Role Center is the user's entry point and home page for Dynamics 365. You can develop several different
Role Centers, where each Role Center is customized to the profile of the intended users. For example, you could
have Role Centers that target the different levels within an organization, such business owners, department
leads, and information workers.
Role Centers are based on a user-centric design model. You should design a Role Center to give users quick
access to the information that is most important to them in their daily work. Like, displaying information that is
pertinent to their role in the company and enabling them to easily navigate to relevant pages for viewing data
and doing tasks.

Role Center structure


A Role Center is defined by page that has the PageType property set to RoleCenter . The Role Center page is
divided into two main areas: navigation/actions area and content area. The following figure illustrates the
general layout and elements of a Role Center page.
For a simple code example of a role center page, see Simple Role Center Code Example.

Navigation and Actions area


The navigation and actions area appears at the top of the Role Center page, and provides links to other objects,
such as pages, reports, and codeunits. You define the navigation area by adding actions to the Role Center page
code, under the actions control in the page code. The navigation and actions area is subdivided into smaller
areas by using different area() controls as described in the following table:

N O. A REA DESC RIP T IO N USA GE GUIDEL IN ES


N O. A REA DESC RIP T IO N USA GE GUIDEL IN ES

1 Navigation menus The top-level navigation The top-level navigation


consists of one or more should provide access to
root menu items that relevant entity lists for the
expand to display links to role's areas of business. For
other pages. The links can example, typical root items
be grouped into submenus, for a business manager
enabling you to create a could be finance, sales, and
logical hierarchy. The pages purchasing. You should
targeted by the links will place the root items in
open in the content area of order of importance,
the Role Center. starting from the left.

You define this area with an


area(Sections) control in
the page code.

2 Navigation bar The second-level navigation You should use these items
displays a flat list of links to to link to users' most useful
other pages. The pages entity lists in their business
targeted by the links will process. For example, with a
open in the content area of business manager, these
the Role Center. could be links to customers,
sales orders, and bank
You define this area with an accounts. You should place
area(embedding) control items in the order that
in the page code. reflects the business
process sequence. Try to
limit the number of second-
level items, and consider
placing items in the top-
level navigation instead, if
the number gets too large.

3 Action bar The actions bar provides The action area is designed
links to pages, reports, and for running the most
codeunits. The links can be important or most often
displayed on the root-level used tasks and operations
or grouped in a submenu. required by users. Actions
The objects targeted by will typically target card
these links will open in a type pages that enable
separate window in front of users to create new entities.
the Role Center page. Such as customers, invoices,
and sales orders, or run
You can define the actions reports. Place the most
by using the three different important action at the
area() controls that are root-level, and group
described in the next closely related actions in a
section. submenu.

Action bar area controls


N O. C O N T RO L DESC RIP T IO N USA GE GUIDEL IN ES

3a area(creation) Actions in this control will Use this control to target


appear first in the action pages that enable the user
area, and will display with a to create new entities.
plus (+) icon.

3b area(processing) Actions in this control will Use this control to target


appear after the pages that are associated
area(creation) items. with the work flow for
You can group actions in processing documents, such
submenus by using a as payments or sales
group control. orders. Use the group
control to organize similar
actions under a common
parent.

3c area(reporting) Actions in this control will Use this control to target


appear last in the action report objects.
area. They display with a
default report icon.

For more information about navigation, see Adding to Navigation.


Behavioral points of interest
The order of the area() controls in the page code isn't important. However, the order of the individual
actions and groups is important because they'll appear in the order in which they appear in page code.
In page code, if the first part in the content area is a Headline part, the actions area in the client will be
automatically positioned. It will be positioned either to the right of the Headline part or after the Headline
part, depending on the browser window size. If the first part isn't a Headline, the actions area will appear
directly after the navigation area, and extend the width of the workspace.
If a welcome banner is displayed on the Role Center, the banner hides the action bar.

Content area
The content area consists of one or more parts that display content from other pages. Unlike the navigation and
actions area that is defined in the Role Center page code, the content area consists of self-contained,
independent page part objects that can be used across Role Centers and in other pages. You define the content
area by adding a layout control in the page code, and then a part control for each individual part to display.
The following table describes some of the most common parts for Role Centers, as illustrated in the previous
figure.

N O. EL EM EN T DESC RIP T IO N M O RE IN F O RM AT IO N

4 Headline Displays a series of Creating Role Center


automatically changing Headlines
headlines that provide users
with up-to-date
information and insight into
the business and daily
work. This is created by a
HeadlinePart page type.
N O. EL EM EN T DESC RIP T IO N M O RE IN F O RM AT IO N

5 Wide data cues A set of cues for displaying Wide Cues


large numbers, like
monetary values. This is
created by using a
cuegroup control on a
CardPart page type,
where the Layout property
is set to wide .

6 Data cues Provide a visual Creating Cues


representation of
aggregated business data,
such as the number of open
sales invoices or the total
sales for the month. These
are created by using a
cuegroup control on a
CardPart page type.

7 Action cues Tiles that link to tasks or Action Tiles


operations, like opening
another page, starting a
video, targeting another
URL, or running code. These
are created by using a
cuegroup control on a
CardPart page type

8 Chart A graphical and interactive


representation of your
business data that can be
sourced by a custom
business chart control add-
in or an embedded Power
BI report.

9 CardPart or ListPart page Displays data fields in a Page Object


form or tabular layout.

10 Control add-in Displays custom content by Control Add-in Object


using HTML-based control
add-in.

Behavioral points of interest


In general, the parts will appear in the client according to the order in which they're defined in the Role
Center page code. They'll automatically rearrange horizontally and vertically to fill the available workspace.
However, in the Web client, page parts that contain cues are automatically grouped under a common
Activities section, no matter where they're placed in the code. All other page parts are grouped under the
Business Assistance section. Within Activities and Business Assistance sections, the parts will arrange
according to the order in which they're defined in the page code.
If a welcome banner is displayed on the Role Center, the banner hides the headline part.

Development tips for overall page design


Don't apply grouping to parts in the content area because it prevents parts from flowing to fill the available
space. This gives the best experience to users with different screen resolutions or those on mobile devices.
To achieve the best readability and discoverability, place Headlines first, followed by cues, and then the
remaining parts.
You can't add custom logic directly to a Role Center page code. Code is limited to defining navigation, actions,
and parts. All other code is ignored.
Role Centers can be highly specialized, in the fact that the navigation, actions, and content are optional. For
example, you could have a single part that fills the entire workspace.

Designing a checklist to onboard new users


Since the Role Center is a user's entry point and home page to Business Central, it's also the ideal space to guide
new users towards learning activities and finalizing setup of their company. The onboarding framework includes
the ability to display a welcome banner and checklist on a Role Center home page. Unlike all other content
described in this article, the welcome banner and checklist require a separate process and aren't implemented
directly on the Role Center page object or page parts. Learn how to get users started with the checklist.

Design for all display targets


Role Center pages are also the primary entry point on mobile devices. Mobile devices will display the same
content as the Web client, but is presented in a different way to suit how users hold and interact with their
mobile device.
You can preview how your Role Center will look on mobile devices directly in Designer.
Some limitations on mobile devices include:
On tablets, there's a limit on the number of cues that can be displayed.
On phones, there's a limit on the number of parts in the content area that can be displayed.
Role Center pages can't be displayed when they're embedded in Outlook or SharePoint.

Performance considerations
Role Centers that have many parts that process data from different sources can degrade performance. To
improve responsiveness and the time it takes to sign in to the Role Center, Business Central 2021 release wave 1
(and later) optimizes the sequence in which content is loaded. The sequence is as follows:
1. Content directly on the Role Center page object is loaded first, and users can immediately interact with it.
Examples of such content are the navigation menu and actions.
2. Parts are loaded one by one from top to bottom.
Parts on which the Visible property evaluates to false won't be loaded.
3. Parts that aren't in view are loaded when the user scrolls to display them.
Here are some practical tips to help you make the most of this optimization:
Consider hiding any parts that represent secondary content that only some users in that role will need. For
more information, see Choosing the visibility of parts.
For parts that require heavy processing, consider applying page background tasks. For more information, see
Using page background tasks.

Using the Role Center in the client


To use or test the new Role Center in the client, you must first associate the Role Center page with a profile.
Profiles define user roles and each profile is associated with a single Role Center page. Create a new profile
object that references your page. Then, go to My Settings and select the new profile.
To let the users use their associated Role Center, you might need to adjust settings for a profile. To manage
settings and profiles, see Define user settings for a profile.

IMPORTANT
Even if you've assigned a role to the user, you can experience a permission issue with an error "You don't have permission
to use the Role Center role center name". To resolve it, make sure the user has all the required permissions and permission
sets. For example, a user has the specific PAGE or TABLE added in the permission set to view it. For more information, see
Assign Permissions to Users and Groups

Customizing a Role Center from the client


Users who work across multiple roles can easily switch Role Centers to shift their focus to different tasks. Users
can also personalize their Role Centers by rearranging or hiding content as they like. For more information, see
Personalizing Your Workspace.
As a developer or administrator, you can use Designer to customize a Role Center the same way that individual
users personalize their own workspaces. The difference is that changes you make are applied to all users
assigned to the Role Center. For more information, see Using Designer.

See Also
AL Development Environment
Page Types and Layouts
Page Extension Object
Actions Overview
Adding Pages and Reports to Tell Me
Personalizing Your Workspace
Using Designer
Simple Role Center Code Example
2/6/2023 • 2 minutes to read • Edit Online

The AL code in this article creates a simple Role Center customized for users assigned to a new profile.

For a more detailed explanation of Role Centers, see Designing Role Centers.
This example uses the RoleCenterHeadline page code example to display the headline and the
SalesInvoiceCuePage page and the following code example for the Cue and Action tile.

page 50125 MyRoleCenter


{
PageType = RoleCenter;
Caption = 'My Role Center';

layout
{
area(RoleCenter)
{
group(Group1)
{
part(Part1; RoleCenterHeadline)
{
ApplicationArea = All;
}

part(Part2; SalesInvoiceCuePage)
{
Caption = 'Invoices';
}
}
}
}

actions
{
area(Sections)
{
group(PostedInvoices)
{
Caption = 'Posted Invoices';
Caption = 'Posted Invoices';
Image = RegisteredDocs;
action(PostedServiceInvoices)
{
Caption = 'Posted Service Invoices';
RunObject = Page "Posted Service Invoices";
ApplicationArea = All;
}

action(PostedSalesInvoices)
{
Caption = 'Posted Sales Invoices';
RunObject = Page "Posted Sales Invoices";
ApplicationArea = All;
}

group(SalesDocuments)
{
Caption = 'Sales Documents';
action("Sales Document Entity")
{
ApplicationArea = All;
RunObject = page "Sales Document Entity";
}
action("Sales Document Line Entity")
{
ApplicationArea = All;
RunObject = page "Sales Document Line Entity";
}
}
}
}

area(Embedding)
{

action(Sales)
{
Caption = 'Sales lists';
RunObject = Page "Sales list";
ApplicationArea = All;
}

action(Services)
{
Caption = 'Service lists';
RunObject = Page "Service list";
ApplicationArea = All;

area(Processing)
{
action(SeeSalesInvoices)
{
Caption = 'See Sales Invoices';
RunObject = Page "Posted Sales Invoices";
}

area(Creation)
{
action(AddSalesInvoice)
{
Caption = 'Add Sales Invoice';
Image = NewInvoice;
Image = NewInvoice;
RunObject = Page "Sales Invoice";
RunPageMode = Create;
}
}

area(Reporting)
{
action(SalesInvoicesReport)
{
Caption = 'Sales Invoices Report';
Image = "Report";
RunObject = Report "Sales - Invoice";
}
}
}
}

// Creates a profile that uses the Role Center


profile MyProfile
{
ProfileDescription = 'Sample Profile';
RoleCenter = MyRoleCenter;
Caption = 'My profile';
}

See Also
AL Development Environment
Page Extension Object
Actions Overview
Adding Pages and Reports to Tell Me
Personalizing Your Workspace
Using Designer
Adding Menus to the Navigation and Actions Area
2/6/2023 • 4 minutes to read • Edit Online

The navigation area appears at the top of the Dynamics 365 Business Central window, and contains multiple
sections that enable users to quickly navigate and perform actions in Dynamics 365 Business Central. In the
client, the navigation area is separated into three separate areas: navigation menu, navigation area, and actions
area. For an illustration that identifies the different areas in a Role Center, see Designing Role Centers. In AL,
these areas are defined by the area() control, as described in the sections that follow.

Adding to the navigation menu


The top-level navigation area is referred to as the navigation menu. The navigation menu contains one or more
root menu items that expand to display links to other pages. The links can be grouped into submenus, enabling
you to create a logical hierarchy. These links are defined by action() controls. You can also group action()
controls in submenus. This enables you to create a logical hierarchy that matches the needs of the user role. The
pages targeted by the links in the navigation menu will open in the content area of the Role Center.

NOTE
The submenu items can include page extensions and other objects like reports, XMLPorts, and codeunits. The Dynamics
NAV Client connected to Business Central doesn't support submenus in the navigation menu.

You define the navigation menu by using an area(Sections) control in the page code.

Example
The example below adds the root menu item called My Customers to the navigation menu of the Sales Order
Processor Role Center. The My Customers menu item contains two actions, the Customer Bank Account List and
Customer Ledger Entries actions, which open corresponding page objects. The My Customers menu item also
includes a group that contains two other actions, which open sales-related documents.
pageextension 50120 ExtendNavigationArea extends "Order Processor Role Center"
{

actions
{
addlast(Sections)
{
group("My Customers")
{
action("Customer Bank Account List")
{
RunObject = page "Customer Bank Account List";
ApplicationArea = All;
}
action("Customer Ledger Entries")
{
RunObject = page "Customer Ledger Entries";
ApplicationArea = All;
}

// Creates a sub-menu
group("Sales Documents")
{
action("Sales Document Entity")
{
ApplicationArea = All;
RunObject = page "Sales Document Entity";
}
action("Sales Document Line Entity")
{
ApplicationArea = All;
RunObject = page "Sales Document Line Entity";
}
}
}
}
}
}

You can also enable pages and reports to appear in the Dynamics 365 Business Central search for a quick
navigational support. For more information, see Adding Pages and Reports to Tell Me.

Adding to the navigation bar


The second-level navigation is referred to as the navigation bar. The navigation bar offers a flat list of links to
other pages. These should be the most relevant pages needed for a user's business process. We recommend
having only the most important items on this level and to place the others in the top-level navigation instead.
You define the navigation bar by using an area(Embedding) control in the page code.
Example
The following code adds a new link to the navigation bar by defining this area with an area(Embedding) control
in the page code. The object targeted in this case is the Sales Cycles page and it will appear as the last one.
...
addlast(Embedding)
{
action("Sales Cycles")
{
RunObject = page "Sales Cycles";
ApplicationArea = All;
}
}

Adding to actions
The actions area displays the most important or most often used tasks and operations required by users. It
contains links to pages, reports, and codeunits. The links are placed on the root-level, and they can be grouped
in a submenu.
You can define the actions by using three different area() controls.
The first action area that appears at the top of the Role Center page is area(Creation) . The following example
adds the item last, and it allows opening the Sales Journal page.
Example

...
addlast(Creation)
{
action("Sales Journal")
{
ApplicationArea = All;
RunObject = page "Sales Journal";
}
}

The actions in the area(Processing) control appears after the area(Creation) items. The example below shows
how you can use the group control to organize similar actions under a common parent. The created group is
placed at the end of this action area, and it targets pages needed for processing sales documents.
Example

...
addlast(Processing)
{
group(Documents)
{
action("Sales Document Entity")
{
ApplicationArea = All;
RunObject = page "Sales Document Entity";
}
action("Sales Document Line Entity")
{
ApplicationArea = All;
RunObject = page "Sales Document Line Entity";
}
}
}

The actions in the area(Reporting) control will appear last in the action area and they display with a default
report icon. This control's purpose is to target report objects and the following example opens the
Customer Sales Statistics report.
Example

...
addlast(Reporting)
{
action("Customer Statistics")
{
ApplicationArea = All;
RunObject = report "Customer Sales Statistics";
}
}

See Also
AL Development Environment
Page Extension Object
Actions Overview
Adding Pages and Reports to Tell Me
Get Users Started with the Checklist
2/6/2023 • 6 minutes to read • Edit Online

When the user hits Get star ted on their Home page, a checklist is revealed inside the banner. The checklist
provides users with an overview of their onboarding activities, while allowing them to learn and explore at their
own pace. The checklist serves as a platform for surfacing page tours, guiding users in the product interface, and
teaching users how to use the app in context. The checklist provides a sense of progression, nudging users to
complete onboarding activities. Users can navigate between the tasks of the checklist at their own pace.
Checklist tasks can point to pages or objects in Business Central or point to external URLs. Read more about the
checklist content in the Prerequisites for creating checklist items section.
As the user progresses through the checklist by either completing or skipping the steps, the banner title and
status indication will change accordingly to nudge and encourage users to finish. At any point, the user can
minimize the banner by hitting X and resume when ready. The following illustration shows the checklist with the
suggested setup and learning material.

The checklist provides an overview of the tasks to complete as well as a detailed description of the ongoing task.
The following illustration shows a Business Central Home page with a collapsed banner, which indicates the
completion progress as well as providing a clear call-to-action to resume with the checklist activities.

What should go into a checklist


Checklists are meant to assist users in finalizing setup and help users get started with using the application.
Checklists are not meant to provide a full list of tasks necessary to set up Business Central from scratch. What
goes into the checklist depends on several factors, but consider bringing Configuration Packages with as much
base setup as possible so the checklist only consists of things where the customer needs to make tweaks and
decisions necessary to support their business. Automation APIs can help you with automating the delivery of
the setup for a customer's industry or segment and applying your IP from AppSource. Using these APIs you
should be able to automate much of the deployment process, including data for the checklist, which enables you
to hand over completion of the setup for the customer. Consider bringing Assisted Setup wizards for the things
that are added to the checklist.
Based on the configuration choices made by the customer in Assisted Setups, you can download additional
modular Configuration Packages necessary to complete the setup. This gives you a lot of flexibility to provide
setup based on customer choices at different stages of the implementation, with the key advantage for you and
the customer that you can spend less time on the actual implementation.

NOTE
The checklist has different purposes in evaluation and non-evaluation companies. Consider this when you add content to
the checklist. For more information, see Onboard New Users with the Welcome Banner].

Technical background of the checklist


The data model of the checklist consists of the following tables. There are more in the data model but these are
the ones you need to know about to provide onboarding experiences to customers.

ID NAME P URP O SE

1991 Checklist Item Represents the checklist item itself.

1992 Checklist Item Role Represents the mapping of checklist


items to roles.

1993 Checklist Item User Represents the mapping of checklist


items to named users.

Prerequisites for creating checklist items


Before you can make a checklist item point to an entity or URL you must add a record to the Guided
Experience Item table that refers to the desired entity.

Guided Experience Item


From the Dynamics 365 Business Central 2021 release wave 1 the records in Manual Setup and Assisted
Setup are migrated to a new table, Guided Experience Item . This table has a field, Type , that determines the
type of each record:
Assisted Setup
This is where all assisted setup wizards now reside.
Manual Setup
This is where all manual setup records now reside.
Learn
Records of type Learn point to an external URL.
Tour
Records of type Tour point to a tour of the role center. Currently, these can only be added by Microsoft in
the Business Central platform. We are considering enabling AL developers to add and control these tours
in time.
Spotlight Tour
Records of type Spotlight Tour point to a special kind of tour where Business Central opens a page in a
special mode that suppresses other tours and shines a bright spotlight on core capabilities, such as Open
in Excel or Share to Teams. Use the spotlight tour in sales and evaluation scenarios to show off key
capabilities that will get customers excited about the product. Consider how you can use these spotlights
for your own or other features. The following illustration shows a spotlight tour that calls out Teams and
Excel integration on a page.

The spotlight tour suppresses teaching tips on the page and immediately calls out Teams and Excel
integration features as shown in the following illustration.

Video
Records of type Video enables the user to watch a video provided by a custom URL. The video will play
in a window inside Business Central. Consider how you can utilize video to explain a feature or capability.
Video is normally used in a sales/evaluation scenario but could also be used for training purposes in an
onboarding case. The following illustration shows a video player that is started from the checklist.
Application Feature
Records of type Application Feature enables a checklist task to open any page inside Business Central.
Similar to Manual Setup this opens a page and will display a page tour if any is defined.
Checklist items can be based on records in the Guided Experience Item table, which means that before you
surface a task on the checklist, you must first add it to Guided Experience Item .
To insert a record in the Guided Experience Item table use the façade functions in the Guided Experience
codeunit:
InsertManualSetup
InsertAssistedSetup
InsertLearnLink
InsertTour
InsertSpotlightTour
InsertVideo
InsertApplicationFeature

For example, let's say that you have the page My ISV Solution Setup where the user can configure your app.
You want to invite the business manager to access this page from the checklist. In this example, you must insert
a new record in the Guided Experience Item table with the type Manual Setup and provide the metadata as
data (title, descriptions, and so on) as described below.
After having created this record, it can now be referenced from and inserted into a checklist.
Best practices for checklist content creation
Do:
Keep the list short (preferably 6 items or less) to avoid a scrollbar and to ensure a successful start for
users.
Keep checklist titles and descriptions short and to the point.
When writing the description, it's good practice to include the benefit of doing the task. But be brief.
TIP
If the task points to a page that comes from the manual setup list, the Shor tTitleChecklist is picked from there. Those
titles consist of nouns such as User permissions .
If the task points to wizards that comes from the assisted setup list, the LongerTitleCard is picked from there. Those
titles usually contain a verb such as Update users .

Don't:
Don't overwhelm the user with a long list of checklist tasks
Don't use too long titles as they're harder to understand and space becomes an issue.
Maximum character UX guideline
Checklist: Shor tTitleChecklist : Max 34 characters before truncation.
Checklist: LongerTitleCard : Max 53 characters before truncation.
Checklist: CardDescription: Max 180 characters before truncation
Client truncation limits
Checklist: Shor tTitleChecklist : Max 34 characters before truncation.
Checklist: LongerTitleCard : Max 53 characters before truncation.
Checklist: CardDescription: A scrollbar appears if the description renders as more than 4 lines.
Auto completion settings and time estimates
Add support for auto-completion when possible, such as for wizards, as this automatically makes the
checklist move to the next task and provides the user with a good sense of progress.
Provide a realistic time stamp of the estimated completion time and strive for tasks that take less than 5
minutes to complete.

See also
Teaching tips and in-app tours for onboarding users
Onboarding experiences in Business Central
Creating a Role Center Headline
2/6/2023 • 5 minutes to read • Edit Online

You can set up a Role Center to display a series of headline texts that appear one by one for a predefined period
of time.

The headlines can provide users with up-to-date information and insight into the business and daily work.
Typical categories of headlines might include:
My performance
My workday
Organizational health
Productivity tips
Cross-tenant insights (performance relative to peers)
Getting started information

IMPORTANT
Headlines will only appear in the Web client; they will not be shown on other client types.

NOTE
Headlines can display numbers and letters only. For example, headlines cannot display images.

Design concept
In development
In short, the Headline is basically a page that contains one or more fields. The page must be the HeadlinePar t
type page. Each field defines an individual headline to be displayed. The source for a field can be an expression
or a field in an underlying table.
The HeadlinePar t page is designed for Role Centers, that is, pages that have the type RoleCenter . If you
use a HeadlinePar t page on another page type, the part will not render in the client.
Using the OnDrillDown trigger, headlines can be made interactive, meaning that users can select the
headline to dig deeper into numbers or values that are shown in the headline or link to another page or
URL.
You can dynamically toggle visibility of a specific headline, for example based on its relevancy, by setting
the Visible property on the field.
There are only a few field properties that apply to fields that are used on a HeadlinePar t type page,
including Expression, Visible, ApplicationArea, Drilldown, and DrillDownPageID. All other properties are
ignored.
In the client
The Role Center will start by displaying the first visible headline that is defined on the HeadlinePart page. The
headline will appear for 5 seconds, then the next headline will appear for 5 seconds, and so on. When all the
headlines have been displayed, it will cycle back to the first headline, and continue from there.
If a headline is interactive, users can select the headline to open the target defined in the headline.
Users can pause on a headline by pointing to it.
Users can manually switch among headlines by selecting a corresponding dot that is displayed under the
headlines.
Users can personalize their Role Center to show or hide the Headline part as they like.

Creating a HeadlinePart page


1. Implement the logic that resolves field expressions for the headlines that you will use on the page.
You can apply more flexible and complex patterns, such as having data tables drive the text, drill-down
and relevance engine for headlines.
2. Create a page that has the PageType property set to HeadlinePart .
3. For each headline, add a field, and set the Expression property. The order of the fields, determines the
order in which they appear.
The following example shows the AL code for a simple HeadlinePar t page that consists of four fields
that display static text.
page 50100 RoleCenterHeadline
{
PageType = HeadLinePart;

layout
{
area(content)
{
field(Headline1; hdl1Txt)
{

}
field(Headline2; hdl2Txt)
{

}
field(Headline3; hdl3Txt)
{

}
field(Headline4; hdl4Txt)
{

}
}
}

var
hdl1Txt: Label 'This is headline 1';
hdl2Txt: Label 'This is headline 2';
hdl3Txt: Label 'This is headline 3';
hdl4Txt: Label 'This is headline 4';
}

4. You can now add the HeadlinePar t page to the RoleCenter page.

Constructing Headlines with the Expression property


The Expression property supports the following syntax that enables you to specify a title for the headline, the
headline text itself, and emphasize a string of text in the headline:

'<qualifier>Title</qualifier><payload>This is the <emphasize>Headline</emphasize>.</payload>'

TA G DESC RIP T IO N

<qualifier></qualifier> Specifies the title that appears above the headline. If you
omit this tag, the text HEADLINE will be used by default.

<payload></payload> Specifies the actual headline text.

<emphasize></emphasize> Applies the style to the text.

The Expression property must evaluate to the correct syntax. For example, looking back at the previous
example, the label hdl1Txt could be:

hdl1Txt: Label '<qualifier>The first headline</qualifier><payload>This is the <emphasize>Headline


1</emphasize>.</payload>';
Making headlines interactive
You can use the OnDrillDown trigger of a headline field to link the headline to more details or relevant
information about what is shown in the headlines. For example, if the headline announced the largest sales
order for the month, you could set up the headline to open a page that shows a sorted list of sales order for the
month.
The following code uses the OnDrillDown trigger to link Headline1 to the Dynamics 365 online help.

field(Headline1; hdl1Txt)
{
trigger OnDrillDown()
var
DrillDownURLTxt: Label 'https://go.microsoft.com/fwlink/?linkid=867580', Locked = True;
begin
Hyperlink(DrillDownURLTxt)
end;
}

Changing the visibility of headlines


You can use the Visible property to show or hide headlines that are defined on the HeadlinePar t page. With the
Visible property, you can show or hide the control either statically by setting the property to true or false , or
dynamically by using a Boolean variable.
Static visibility
With static visibility, you can simply set the Visible property on specific fields. For example, following code
hides Headline3 :

{
field(Headline1; hdl1Txt)
{

}
field(Headline2; hdl2Txt)
{

}
field(Headline3; hdl3Txt)
{
Visible=false;
}
field(Headline4; hdl4Txt)
{
}
}

By adding fields under Group controls, you can hide or show more than one headline by setting the Visible
property on the Group control. For example, the following code hides headings Headline3 and Headline4 :
group(Group1)
{
field(Headline1; hdl1Txt)
{
}
field(Headline2; hdl2Txt)
{

}
}
group(Group2)
{
Visible=false;
field(Headline3; hdl3Txt)
{
}
field(Headline4; hdl4Txt)
{
}
}

IMPORTANT
Unlike other page types, the group control has no effect on the UI on pages of type HeadlinePar t . Its primary purpose
is to enable developers to group headlines for controlling visibility.

Dynamic visibility
With dynamic visibility, you can show or hide a headline based on a condition that evaluates to true or false .
To dynamically show or hide a headline when the HeadlinePar t page opens, the headline field must be
in group control, and you set the Visible property on the group control to the Boolean variable that
determines the visibility. For example, you could add code on the page's OnAfterGetRecord trigger that
evaluates the relevance of displaying Headline3 and results in a Boolean variable being set to true or
false .

To dynamically show or hide a headline while a page is open, you set the Visible property on the field
control to the Boolean variable that determines the visibility.
group(Group1)
{
field(Headline1; hdl1Txt)
{
}
field(Headline2; hdl2Txt)
{

}
}
group(Group2)
{
// Determines visibility when the page opens
Visible=ShowHeadline3;
field(Headline3; hdl3Txt)
{
// Determines visibility while the page is open
Visible=ShowHeadline3;
}
field(Headline4; hdl4Txt)
{
}
}

See Also
Pages Overview
Page Object
Creating Cues and Action Tiles on Role Centers
2/6/2023 • 6 minutes to read • Edit Online

This article provides an overview of Cues and Action tiles. Learn about the tasks involved in creating and
customizing them for displaying on Role Centers, as illustrated in the following figure:

NOTE
Modifying actions in Cue groups on page extensions isn't supported.

Designing Cues
A Cue provides a visual representation of aggregated business data, like the number of open sales invoices.
Cues are interactive, meaning that you can select the Cue to drill down to data or open another page, run code,
and more. Cues display data that is contained in a table field. This data can be raw data or calculated data.
Normal and wide layout
There are two layout options that influence how Cues appear in the client: normal and wide.
The normal layout displays Cues as tiles. With this layout, Cue groups are automatically arranged to fill in
the width of the workspace, which means there can be more than one group horizontally across the
workspace.
The wide layout is designed to display large values, such as monetary values. The wide layout gives you a
way emphasize a group of Cues. Wide and normal Cue groups can be interleaved. However, wide groups
that precede all normal groups will appear in their own section of the workspace, spanning the entire
width - providing space for the large values. Wide groups that are placed after normal groups will behave
just like the normal layout groups. So, it's good practice to place Cue groups that use the wide layout,
above those Cues that use the normal layout. The wide layout is specified by setting the CuegroupLayout
property to wide .
NOTE
The wide layout is only supported in the Web client.
The Caption and CaptionML properties of the cuegroup control are ignored when the layout is wide.

Supported data types


You can only base Cues on integer and decimal data types. Other data types aren't supported and won't display
in a Cue.
FlowFields versus normal fields
A Cue can be based on a FlowField or Normal field.
If you base the Cue on a FlowField, add the logic that calculates the data for the Cue to the CalcFormula
property of the FlowField.
If you use a Normal field, you'll typically add the logic that calculates the Cue data to an AL trigger or
method.
Unlike a FlowField, where data is extracted from tables, a Normal field enables you to extract data from
other objects such as queries.
Creating a Cue
The implementation of a Cue involves the following elements:
A table object with a field that holds the data that is contained in the Cue at runtime.
A page object that contains the table field and displays the Cue in the client.
Logic that calculates the data to display in the Cue at runtime.
The logic can consist of AL code and objects, like tables, queries, and codeunits. The design will depend on
whether the Cue is based on a FlowField or Normal field.

NOTE
The examples in this section will set up a Cue that extracts the number of open sales invoices from the Sales Header
table.

Create a table for Cue data


The first thing that you must do is to create a table that contains fields that will hold the calculated data to
display in the Cues at runtime.
1. Create a table object or use an existing one.
2. Add fields for the Cue data.
For each Cue that you want to display on the page, you must add a Field control in the table object.
When you add the Field control, specify the following properties:
Set the Data Type property to Decimal , Integer , or Text , depending on the type of data the Cue
will display.
Set the FieldClass property to FlowField or Normal .
If field is a FlowField, then set the CalcFormula property to calculate the Cue data. For more
information, see Calculation Formulas and the CalcFormula Property.
3. Add a primary key field for FlowFields.
A table must have at least one data field. Because a FlowField is based on a calculation, it not considered
an actual data field. So, if the Cue table only includes FlowFields, you must add "dummy" primary key
field that doesn't yield any data.
To add primary key, for example, add a field with the name Primar y Key , and then set its data type to
Code .
Example

table 50100 SalesInvoiceCueTable


{
DataClassification = ToBeClassified;

fields
{
field(1;PrimaryKey; Code[250])
{

DataClassification = ToBeClassified;
}
field(2; SalesInvoicesOpen ; Integer)
{
FieldClass = FlowField;
CalcFormula = count("Sales Header" where("Document Type"=Filter(Invoice), Status=FILTER(Open)));

}
}

keys
{
key(PK; PrimaryKey)
{
Clustered = true;
}
}
}

Add Cues to a Page object


After you have a table for holding the Cue data, you create a page that you associate the table, and then add Cue
fields on the page. Typically, you'll create Card Part type page that will be part of the Role Center page. Cues are
arranged into one or more groups on the page. Each group will have its own caption.
1. Create a page object that has the SourceTable property set to the Cue data table.
2. Add a cuegroup control.
3. Under the cuegroup control, for each Cue that you want to display, add a field control.
4. Set the field's Caption property or CaptionML property to specify the label that will appear on the Cue.
These properties also specify the heading in the drill-down page.

NOTE
You can't use the CaptionClass property for this purpose.

5. If you want to set the cuegroup to use the wide layout, set the CuegroupLayout property to wide .
Repeat steps 2-4 to add more Cue groups.
6. Initialize the Cue fields.
To initialize the fields, for example, you can add the following AL code to the OnOpenPage Trigger.

RESET;
if not get then begin
INIT;
INSERT;
end;

Example

page 50105 SalesInvoiceCuePage


{
PageType = CardPart;
SourceTable = SalesInvoiceCueTable;

layout
{
area(content)
{
cuegroup(SalesCueContainer)
{
Caption='Sales Invoices';
// CuegroupLayout=Wide;
field(SalesCue; SalesInvoicesOpen)
{
Caption='Open';
DrillDownPageId="Sales Invoice List";
}
}
}
}

trigger OnOpenPage();
begin
RESET;
if not get then begin
INIT;
INSERT;
end;
end;
}

Designing Action tiles


Action tiles promote an action or operation to the user on the Role Center. Action tiles act as links that run a task
or operation. For example, an action tile could open another page, start a video, target another resource or URL,
or run code. They'll arrange on the workspace just like that use the normal layout.
Similar to Cues, Actions tile can be grouped together, under a common caption, by using the cuegroup control.
The difference is that instead adding field controls under the cuegroup control, you create Action tiles by adding
actions to the cuegroup control.
Create an Action tile
1. Develop or locate the functionality that you want to Action tile to do.
For example, create the page object that you want the Action tile to open. Or, add AL code that you want
the Action tile to run.
2. Add a cuegroup control where you want the Action group.
3. Configure the control to the wanted operation.
For example, if it should open a page, set the control's RunObject property to the appropriate page. Or,
set it to call a function or method.
Example
The following code adds an Action tile that opens Sales Invoice page.

cuegroup(SalesActionontainer)
{
Caption='New Sales Invoice';

actions
{

action(ActionName)
{
RunObject=page "Sales Invoice";
Image=TileNew;

trigger OnAction()
begin

end;
}
}
}

Styling an Action tile


You can use the Image property on an action control to change the look of the Action tile. For Action tiles, the
Image property supports several standard values that start with the text Tile , such as TileNew and
TileYellow . These values change the Action's background color and icon as follows:

A value that has the format Tile[color] will set the Action tile to use the circle icon and a background
that is specified by [color] . For example, TileBlue will display a circle icon in a blue background.
A value that has the format Tile[picture] will set the Action tile to use an icon that is specified by
[picture] and a neutral background color. For example, TileCamera will display a camera icon on the
neutral background.

NOTE
If you use a value that isn't valid or recognized, the Action tile will default to display the circle icon on the neutral
background.

See Also
FlowFields
Page Object
Pages Overview
Table Object
Pages Overview
2/6/2023 • 7 minutes to read • Edit Online

In Dynamics 365 Business Central, pages are the main way to display and organize data. Pages are the primary
object that a user will interact with and have a different behavior based on the type of page that you choose.
Pages are designed independently of the device they are to be rendered on, and in this way the same page can
be reused across phone, tablet, and web clients.
A page is defined in code as an object composed of controls, properties, actions, and triggers. You can also use
Designer in Dynamics 365 Business Central to create a page. For more information, see Using Designer.
Whether you are creating a new page, or extending an existing page, you will add a new .al file to your project
and describe the page object in code. The difference is basically that for a new page, you need to define the
entire page, whereas when modifying an existing page, you only add the extra functionality or modify the
existing.
The structure of a page is hierarchical and breaks down in to three sections. The first block contains metadata for
the overall page. The metadata describes the page type and the source table it is showing data from. The next
section; the layout, describes the visual parts on the page. The final section details the actions that are published
on the page.
Furthermore, the page has properties. Properties work in the same way for pages as they do for other Dynamics
365 Business Central objects. For more information, see Page Properties.

TIP
For information about designing pages, see Page Types and Layouts.

Page metadata
For a new page object, you must at least specify the type of page; PageType and the data source; SourceTable of
the page. And you can also set other metadata at the beginning of the declaration of the page object.

page 50102 PageName


{
PageType = List;
SourceTable = TableName;
Editable = true;
ContextSensitiveHelpPage = 'feature-overview';
...
}

Types of pages
Which page type you choose depends on the application task that you want to support, the content that you
want to display, and how you want to display it. The Role Center page is the main or home page and it helps the
user focus on the most important daily tasks and activities. Other types of pages, such as list pages or card
pages are typically linked from the home page for easy access. The following page types are available:

PA GE T Y P E DESC RIP T IO N
PA GE T Y P E DESC RIP T IO N

RoleCenter The Role Center page is the main page.

Card A Card page is used to view and edit one record or entity
from a table.

CardPart A Card Part page is used in a FactBox on another page to


view or edit additional fields associated with a selected entity
in the page.

List A List page displays content from a table in a list format.

ListPart Similar to a List page, a List Part page displays content from
a table in a list format. The difference is that you use the List
part page as another page in a FactBox or as a part of the
Role Center page.

ListPlus A ListPlus page displays content from a table in a list format.


The difference from a List page is that the main content is a
ListPart, not a Repeater group as the List has it.

Document A Document page usually consists of two separate pages


combined into one, with one page nested in the other. A
Document page is suitable for use when you want to display
data from two tables that are linked together.

WorkSheet You use a Worksheet page type for creating worksheet or


journal task pages.

ConfirmationDialog You use the ConfirmationDialog page to display messages or


prompt users with a confirmation before they continue with
the task that they are working on.

StandardDialog The StandardDialog is a simple page type that you use when
users only need to input data and do not need to perform
other actions from the page.

NavigatePage You use a Navigate page type to create an assisted setup


guide, also known as a wizard, that leads the user through a
sequence of steps for completing a task.

HeadlinePart You use a HeadlinePart page type to display a set of


changing headlines on a Role Center.

API Pages of this type are used to generate web service


endpoints and cannot be shown in the user interface. This
page type should not be extended by creating a page
extension object. Instead, create a new API by adding a page
object.

NOTE
For backwards compatibility we continue to support adding non-part pages as parts. We do, however, recommend that
you redesign your page to only use Card part or List part, as we may remove support in a future update.
Page layout
The page layout of the page object determines what the page will look like and is specified in the layout
section. The layout contains one or more area sections that define a certain placement on the page.
You can choose between the following area categories:

A REA T Y P E P L A C EM EN T O N T H E PA GE

Content The content area displays the content of, for example, a
RoleCenter or a List page.

FactBoxes The FactBox area is placed to the right-most side of a page.


Displays content related to an item on the main content
page.

RoleCenter The RoleCenter is the main page of the application and is


used for quick access to frequently used information and
tasks.

Page actions
All pages contain menu items and navigation controls called actions. In Dynamics 365 Business Central, actions
are displayed at the top of each page in the ribbon or in the navigation pane. The actions section of the page
describes what the user is able to do on a page and must be designed with the user's need for process support
in mind.
Actions can be displayed in the ribbon of all pages and grouped together under the following actions tabs:
Home
Actions
Navigate
Report
Creating actions can include adding activity buttons/cues to a page, configuring navigation items on a user role
center, or adding Reports to a page. To learn how you can enable users to quickly locate the actions they want to
use, see Actions.

Adding Help to the page objects


The Business Central user assistance model expects your solution to include tooltips and links to context-
sensitive Help. For more information, see User Assistance Model.
Context-sensitive Help
To apply context-sensitive Help to your app, you specify a URL to your Help library in the app.json file, and you
then set the relevant target Help files as property values for each of your page objects and page extension
objects. Between them, these two settings then give users access to context-sensitive Help for the features in
your app at runtime. For more information, see Configure Context-Sensitive Help.
Tooltips
In combination with descriptive captions and instructional text, tooltips are our current implementation of
embedded user assistance, which is an important principle in today’s world of software design. The tooltips are
there to help users unblock themselves by providing an answer to the most likely questions the users might
have, such as “What data can I input here?” or “What is the data used for?”.
The base application has set the Tooltip property for all controls on (almost) all page objects. Most system
actions also include tooltips so that users get a consistent experience. Your extensions are expected to also
include tooltips for the same reason. For more information, see ToolTip Property.
Instructional text
The base application has applied instructional text to setup guides and certain other types of page objects. Your
extensions are expected to also include instructional text to setup guides for the same reason. For more
information, see InstructionalText Property.
Example
The following example shows how you can apply user assistance and link to Help in a page object:

page 50101 "Reward Card"


{
PageType = Card;
SourceTable = Reward;
ContextSensitiveHelpPage = 'sales-rewards';

layout
{
area(content)
{
group(Reward)
{
InstructionalText = 'Fill in the fields so that you can reward customers with discounts.';
field("Reward Id"; "Reward ID")
{
ApplicationArea = All;
ToolTip = 'Specifies the unique ID of the reward.';
}

field(Description; Description)
{
ApplicationArea = All;
ToolTip = 'Specifies what this type of reward is used for.';
}

field("Discount Percentage"; "Discount Percentage")


{
ApplicationArea = All;
ToolTip = 'Specifies the impact of the reward on the customer''s price.';
}
}
}
}
}

In this example, the app.json file has specified a link to where the sales-rewards target file is published, such as
"contextSensitiveHelpUrl": "https://mysite.com/documentation" .

Best practices for designing pages


We recommend that you simplify the user experience by reducing what users see by default. You can promote
the information that the users most frequently need to see and hide the less important information. For
example:
Place common tasks in the ribbon
Organize information pages under FastTabs and, by default, hide the FastTabs that are infrequently visited.
Use one to three FactBoxes on a page to provide supplementary information and a place for adding notes
Add a target Help file for context-sensitive Help for the feature that the page object supports
See Also
Page, Page Fields, and Page Extension Properties
Actions Overview
Using Designer
Page Types and Layouts
Adding a Factbox to a Page
Designing Role Centers
Configure Context-Sensitive Help
Page Object
2/6/2023 • 2 minutes to read • Edit Online

Pages are the main way to display and organize visual data in Dynamics 365 Business Central. They are the
primary object that a user will interact with and have a different behavior based on the type that you choose.
Pages are designed independently of the device they are to be rendered on, and in this way the same page can
be reused across phone, tablet, and web clients.
The structure of a page is hierarchical and breaks down in to three sections. The first block contains metadata for
the overall page; the type of the page and the source table it is showing data from. The next section; the layout,
describes the visual parts on the page. The final section details the actions that are published on the page.
When developing a solution for Dynamics 365 Business Central, you will follow the code layout for a page as
shown in the page example below, but for more details on the individual controls and properties that are
available, see Page Property Overview.
If you want to, for example, add functionality to a page that already exists in Business Central, you can create a
page extension object that changes an existing page object. For more information, see Page Extension Object.
Depending on how much you want to change on an existing page, you can also create a page customization
object, which offers modifications on actions and layout. For more information, see Page Customization Object.

IMPORTANT
Only pages with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

Snippet support
Typing the shortcut tpage will create the basic layout for a page object when using the AL Language extension
in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Views
Views in Dynamics 365 Business Central are used on list pages to define a different view of the data on a given
page. Views can be defined for Pages, Page Extensions, and Page Customization. For more information, see
Views.

Page example
page 50101 SimpleCustomerCard
{
PageType = Card;
SourceTable = Customer;
ContextSensitiveHelpPage = 'my-feature';

layout
{
area(content)
{
group(General)
{
field("No."; "No.")
{
ApplicationArea = All;
CaptionML = ENU = 'Hello';

trigger OnValidate()
begin
if "No." < '' then
Message('Number too small')
end;
}

field(Name; Name)
{
ApplicationArea = All;
}
field(Address; Address)
{
ApplicationArea = All;
}
}
}
}
actions
{
area(Navigation)
{
action(NewAction)
{
ApplicationArea = All;
RunObject = codeunit "Document Totals";
}
}
}
}

See Also
AL Development Environment
Views
Adding Help Links from Pages, Reports, and XMLports
Page Extension Object
Page, Page Fields, and Page Extension Properties
Page Properties
Developing Extensions
Configure Context-Sensitive Help
Page Extension Object
2/6/2023 • 4 minutes to read • Edit Online

The page extension object extends a Dynamics 365 Business Central page object and adds or overrides the
functionality.
The structure of a page is hierarchical and breaks down into three sections. The first block contains metadata for
the overall page; the type of the page and the source table it is showing data from. The next section; the layout,
describes the visual parts on the page. The final section details the actions that are published on the page.
For more information about the Page and Page Extension objects, see Pages Overview.

IMPORTANT
Only pages with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

IMPORTANT
The API page type should not be extended by creating a page extension object. Instead, create a new API by adding a
page object.

NOTE
Modifying actions in Cue groups on page extensions is not supported.

Snippet support
Typing the shortcut tpageext will create the basic layout for a page extension object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Views
Views in Dynamics 365 Business Central are used on list pages to define a different view of the data on a given
page. Views can be defined for Pages, Page Extensions, and Page Customization. For more information, see
Views.

Using keywords to place actions and controls


You can use the following keywords in the layout section to place and move fields and groups on the page
extension. Similarly, in the actions section, you use these keywords to place actions in the ribbon.

K EY W O RDS SY N TA X A P P L IES TO

addfirst addfirst(Anchor) Anchor : areas and groups

addlast addlast(Anchor) Anchor : areas and groups

addafter addafter(Anchor) Anchor : controls, actions, and groups

addbefore addbefore(Anchor) Anchor : controls, actions, and groups

movefirst movefirst(Anchor; Target1, Anchor : area, group


Target2) Target : list of actions or list of controls

movelast movelast(Anchor; Target1, Anchor : area, group


Target2) Target : list of actions or list of controls

moveafter moveafter(Anchor; Target1, Anchor : controls, actions, and groups


Target2) Target : list of actions or list of controls

movebefore movebefore(Anchor; Target1, Anchor : controls, actions, and groups


Target2) Target : list of actions or list of controls

modify modify(Target) Target : controls, actions, and groups

Example
To modify the existing fields and groups on a page, you use the modify keyword. See the code snippet below
for addlast , modify and action syntax. In the following example, the actions section creates a new group in
the ribbon and places it last in the Creation group.
pageextension 70000020 CustomerCardExtension extends "Customer Card"
{
layout
{
// Adding a new control field 'ShoeSize' in the group 'General'
addlast(General)
{
field("Shoe Size"; ShoeSize)
{
Caption = 'Shoe size';

trigger OnValidate();
begin
if (ShoeSize < 10) then
Error('Feet too small');
end;
}
}

// Modifying the caption of the field 'Address'


modify("Address 2")
{
Caption = 'New Address 2';
}

// Moving the two fields 'CreditLimit' and 'CalcCreditLimitLCYExpendedPct'


// to be the first ones in the 'Balance' group.
movefirst(Balance; CreditLimit, CalcCreditLimitLCYExpendedPct)
}
actions
{
// Adding a new action group 'MyNewActionGroup' in the 'Creation' area
addlast(Creation)
{
group(MyNewActionGroup)
{
action(MyNewAction)
{
Caption = 'My New Action';

trigger OnAction();
begin
Message('My message');
end;
}
}
}
}
}

tableextension 70000020 CustomerTableExtension extends Customer


{
fields
{
// Adding a new table field in the 'Customer' table
field(50100; ShoeSize; Integer) { }
}
}

Page extension examples


In the following example, we use a table extension to extend the Customer table with a new field named
ShoeSize of the datatype Integer. Then we create a page extension object that extends the Customer Card page
object by adding a field control ShoeSize to the General group on the page. The field control is added as the
last control in the group using the addlast method. The example also illustrates how to add a display-only
control to the page. In the actions area, you can see what the syntax looks like for actions that execute triggers
and actions that run objects.

tableextension 50115 RetailWinterSportsStore extends Customer


{
fields
{
field(50116;ShoeSize;Integer)
{
Caption = 'ShoeSize';

trigger OnValidate();
begin
if (rec.ShoeSize < 0) then
begin
message('Shoe size not valid: %1', rec.ShoeSize);
end;
end;
}
}

procedure HasShoeSize() : Boolean;


begin
exit(ShoeSize <> 0);
end;

trigger OnBeforeInsert();
begin
if not HasShoeSize then
ShoeSize := Random(42);
end;
}

pageextension 50110 CustomerCardExtension extends "Customer Card"


{
layout
{
addlast(General)
{
// control with underlying datasource
field("Shoe Size"; ShoeSize)
{
ApplicationArea = All;

trigger OnValidate();
begin
if (ShoeSize < 10) then
Error('Feet too small');
end;
}
// display-only control (without underlying datasource)
field(ShoesInStock; 10)
{
ApplicationArea = All;
Caption = 'Shoes in stock';

}
}

modify("Address 2")
{
Caption = 'New Address 2';
}
}

actions
{
{
addlast(Creation)
{
group(MyActionGroup)
{
Action(MyAction1)
{
ApplicationArea = All;
Caption = 'Hello!';

trigger OnAction();
begin
Message('My message');
end;
}

Action(MyAction2)
{
ApplicationArea = All;

// Run page to test how actions work


RunObject = page "Absence Registration";
}
}
}
}
}

You can reference Report and XMLPort objects and use these objects in the RunObject property, as well as,
declare variables of the types Repor t and XMLPor t and call AL methods on them. This page extension object
extends the Customer List page object by adding two actions; the first action calls the Customer - List report,
the second action calls the Expor t Contact XMLPort.

pageextension 50114 AddCustomerReport extends "Customer List"


{
actions
{
AddLast("&Customer")
{
action("Customer List Report")
{
trigger OnAction();
var
rep : Report "Customer - List";
begin
rep.Run;
end;
}

action("Export Contact List")


{
trigger OnAction();
var
xml : XmlPort "Export Contact";
begin
xml.Run;
end;
}
}
}
}

See Also
Page Object
Views
Page, Page Fields, and Page Extension Properties
Extending Pages Previously Based on the Date Virtual Table Developing Extensions
AL Development Environment
Adding Pages and Reports to Tell me
2/6/2023 • 4 minutes to read • Edit Online

The Business Central client includes the Tell me feature that lets users find objects by entering search terms.
When you have added a page or a report in your extension, you most likely want it to be discoverable to users
in Tell me . In AL, you make a page or report searchable from Tell me by setting the UsageCategory property in
code. The UsageCategor y setting will make the page or report searchable, and the value chosen for the setting
will further sub categorize the item.
Tell me finds pages and reports by searching the captions that are specified on page and report objects by the
CaptionML property.

Working with the UsageCategory property


When you create a Page or a Report, you add the UsageCategory Property. If the UsageCategor y is set to
None , or if you do not specify UsageCategor y , the page or report will not show up when you search in
Dynamics 365 Business Central.

TIP
The UsageCategor y is also used to categorize pages and reports shown in the role explorer of the client. The role
explorer includes two actions: Repor ts and Analysis and Administration . Pages and reports set to
Repor tsAndAnalysis will show when the Repor ts and Analysis action is selected. Pages and reports set to
Administration will show when the Administration action is selected. For more information, see Finding Pages with
the Role Explorer.

UsageCategory property values


The values for the UsageCategor y property are listed below. The sub category will help the user navigate
through the search results and it is a best practice to be consistent when categorizing the pages and the reports
that you add. A consistent approach will help guiding the user and improve productivity.

VA L UE DESC RIP T IO N

None The page or report is not included in search.

Lists The page or report is listed as Lists under the Pages and
Tasks category.

Tasks The page or report is listed as Tasks under the Pages and
Tasks category.

ReportsAndAnalysis The page or report is listed as Repor ts and Analysis


under the Repor ts and Analysis category.

Documents The page or report is listed as Documents under the


Repor ts and Analysis category.

History The page or report is listed as Archive under the Repor ts


and Analysis category.

Administration The page or report is listed as Administration under the


Pages and Tasks category.

Adding additional search terms


You can specify other words or phrases that can help users find a page or report by using the
AdditionalSearchTerms and AdditionalSearchTermsML properties. If the page or report is searchable by Tell me
(that is, th UsageCategor y property is set a value other than None ), the search terms specified by these
properties are used in addition to the caption of the page or report. These properties are useful when the
caption does not always reflect what users will look for. A good example of this in Business Central is pages and
reports associated with Item . Users unfamiliar with Business Central might look for 'product' or 'merchandise'
instead of 'item'.
NOTE
For Business Central on-premises, the Business Central Web Server configuration file (navsettings.json) includes a setting
called UseAdditionalSearchTerms that enables or disables the use of additional search terms by the Tell me . For more
information, see Configuring Business Central Web Server Instances.

Example
The following example creates a SimpleItemList page and sets a UsageCategory property to the page, so that
the SimpleItemList page is discoverable through search using the Tell me feature. Also, the example sets the
AdditionalSearchTerms property to add two search terms for the page.

page 50210 SimpleItemList


{
PageType = List;
SourceTable = Item;
UsageCategory = Lists;
AccessByPermission = page SimpleItemList = X;
ApplicationArea = All;
AdditionalSearchTerms = 'product, merchandise';

layout
{
area(content)
{
group(General)
{
field("No.";"No.") {}
field(Name;Name) {}
field(Description;Description) {}
}
}
}
}

Optional settings
In addition to making a page or report searchable, you can control the access of an object by providing Read ,
Inser t , Modify , Delete , and Execute (RIMDX) permissions by adding the AccessByPermission property.
Likewise, control the application area access on the specified object by adding the ApplicationArea Property.
The AccessByPermission property and ApplicationArea property are the optional settings, which can be
applied with the UsageCategor y property. These settings are used to set restrictions on an object when you
enable the Search functionality.

Working in the Dynamics NAV Development Environment


NOTE
Dynamics NAV Development Environment is DISCONTINUED AFTER: Business Central Spring 2019.

If you are using the Dynamics NAV Development Environment, you can also set UsageCategor y ,
AdditionalSearchTerms , AccessByPermission , and ApplicationArea properties on pages and reports to
control their search.
After you change these properties by using the Dynamics NAV Development Environment, before the changes
take effect in the client, you must run Build Object Search Index from the Tools menu.

See Also
Adding Menus to the Navigation Pane
UsageCategory Property
Page Object
Report Object
AL Development Environment
Page Types and Layouts
2/6/2023 • 15 minutes to read • Edit Online

Understanding how Business Central displays a page dependent on its page type is important to be able to
create a good user experience. There are also several page properties and variations of the page structures that
can help create an intuitive and efficient user interface.
In this article, we're focusing on how pages appear when a user accesses Business Central from a desktop
browser. But it's an important point that the same page types apply across the different form factors of apps,
and the Business Central page type layouts automatically adapt to work well on different devices, like on a
phone or a tablet.

Understanding page types


Choosing the right page type is the first step when creating or modifying a page. The next step is to organize the
page contents to suit its purpose in your solution. We recommend that you design pages based on the user
tasks that you want to support.
The following table provides an overview of the page types supported in Business Central, their typical uses, and
basic characteristics. To specify the page type, use the PageType property. For more information, see PageType
Property.

PA GE T Y P E EXA M P L ES O F USE M A IN DATA DISP L AY C H A RA C T ERIST IC S

RoleCenter Overview of business Defined by the embedded A collection of parts (Cues,


performance and the start parts. KPIs, etc.) and the contents
page for a specific user of the navigation pane.
profile.

Card Master, reference, and set Single entity Titled entity with FastTabs.
up data management. Card May embed parts.
page example

Document Transaction and other Single entity Titled entity with FastTabs.
document management. Should have the document
lines ListPart immediately
follow the header section(s).

ListPlus Statistics, details, and Single entity Titled entity with at least
related data management. one ListPart . Can have
fields above or below the
part(s).

List Entity overviews and Collection of entities/entries A single list with a caption.
navigation, and inline May have field groups and
editing of simple entities. subpages above and below
List page example the list's Repeater .

Worksheet Line-based data entry tasks Collection of entities A single list or table with a
(such as journals) and caption. May have field
inquiries. groups and subpages
above and below the
worksheet's Repeater .
PA GE T Y P E EXA M P L ES O F USE M A IN DATA DISP L AY C H A RA C T ERIST IC S

StandardDialog Routine dialog that starts or Single or collection A cancelable dialog with an
progresses a task. instruction to the user. Can
have one or more groups of
fields and parts.

ConfirmationDialog Confirmative or exceptional Single or collection A Yes/No dialog with an


dialog, such as warnings. instruction to the user. Can
have one or more groups of
fields and parts.

NavigatePage Multi-step dialog (also Single or collection Can have one or more
known as a "Wizard"). groups of fields and parts.

CardPart A page that is embedded in Single entity Single group of fields


another page, such as in a representing fields in a
FactBox. FastTab.

ListPart A page that is embedded in Collection of entities/entries Single Repeater


another page, such as in a representing columns in a
FactBox. list or table. Can have fields
above or below the
repeater.

HeadlinePart A page that is embedded in Single entity Single group of fields


a RoleCenter page to representing headlines.
display relevant insights
from across the business.

The two principal categories of page types


A fundamental characteristic of a page type is how it relates to the data presented on the page. Two principal
ways exist: entity-oriented (typical for the Card page type) and collection-oriented (typical for the List page
type.)

CARD , DOCUMENT , AND LISTPLUS LIST AND WORKSHEET

The entity-oriented page types have actions (in top and in The collection-oriented page types provide actions in
action bar) that affect the entity or context given by the title action bar (and on the rows' action menu) that take effect on
of the page. the selected row(s) in the collection.

Entity-oriented pages
In Business Central, entity-oriented pages are used to support users when their tasks revolve around a single
business entity. The most typical entity-oriented page is the Card , which provides details about a single
customer or other master data, and the Document , which represents a single transaction, or other important
business event, for example, a sales transaction.
ListPlus is also an entity-oriented page type. Unlike Card and Document pages, the ListPlus page type is for
pages that have a prominent ListPart and either few or no header fields.
The CardPart page type is an entity-oriented page type for inclusion in another page, for example, in a FactBox.
IMPORTANT
Because entity-oriented pages represent a single entity, such as a customer or an item, don't use a Repeater group in
the construction of entity-oriented pages. If you do, some of the repeater's features may not work properly, and it may
not get the expected size. However, an entity-oriented page can embed a ListPart part page that, in turn, contains a
repeater control. Learn more about how to user repeater controls Working with Repeater Controls.
If you currently have an entity-oriented page that uses a repeater, in most cases, you can just change the page type from
Card to List , or CardPart to ListPart . In some cases, it is more complicated. For example, if the page has actions
that act on the grid or variables that are used in the grid.

Collection-oriented pages
In Business Central, collection-oriented pages are used to support users when their tasks involve multiple
entities or records at the same time. The most typical collection-oriented page type is the List (for example
showing customers, items, and so on.) from which the user can seek out the entities to work with.
The Worksheet is the other prominent collection-oriented page type, suited for data entry (for example, in
journal pages) and other tasks related to managing a set of entities/entries based on custom fields above and/or
below the collection.
The ListPart page type is a collection-oriented page type for inclusion in another page, for example, in a
FactBox.
Dialog pages
The page types in Business Central that are available exclusively for displaying dialogs, such as the
StandardDialog and ConfirmationDialog page types, can represent an entity or a collection. The title caption and
actions are suited for both types.

Composing pages
Within a page, the developer can combine page fields into groups. Groups help the user overview the page by
placing related fields together. And within a group, subgroups further increase the structure of the data
displayed in a page.
Besides adding fields and groups to a page, it's possible to embed another page of type CardPart or ListPart .
(These two page types can in turn not embed other pages.)
When pages are created that embed parts, Business Central divides the available screen real estate between the
page's groups of fields and any embedded pages. Screen space is divided between field groups and embedded
pages, so that the user can get access to the full contents of the page and collapse/expand specific sections of
interest.
How space allocation takes place for a given page depends on the chosen page type, the structure of page
contents (field groups and page parts), and on the size of the browser window.
A page is Content + Actions + FactBoxes
For all pages (excluding RoleCenter , dialogs, and part pages) there's a common structure to the areas of a page
where content, FactBoxes, and actions can be displayed.
The content area provides rich layout capabilities, which are described in the coming sections. The FactBoxes
area is limited to showing a list of parts, usually in a vertical arrangement. The header consists of the title, action
bar, and controls for filtering, views, and so on.
For more information about page areas, see Pages Overview.
Field groups and page parts
In the following sections, you find descriptions of typical page layouts, recommendations for how to organize
the contents, and illustrations of the principles by which the sections of page share screen real estate. The types
of content on a page are illustrated this way:

SY M B O L SEC T IO N N OT ES

Group of fields, or CardPart Appears on the page as a FastTab, with


fields wrapped in one or more
columns.

ListPart List or table layout, with integrated


action bar.

Repeater List or table layout.

Sizing of page sections


The groups of fields and page parts making up a page are rendered when the user opens the page.
Dependent on the size of the available screen real estate, for example, in the browser window on a desktop
computer, Business Central sizes the sections automatically to make the most of the space.
There are three different ways a section's size are determined.

SY M B O L L AY O UT B EH AVIO R N OT ES

Size to content Enclosing page will use a scrollbar if


needed.
SY M B O L L AY O UT B EH AVIO R N OT ES

Size to content within certain limits The part will use a scrollbar if content
exceeds available space.

Size to fill space The part will use a scrollbar if content


exceeds available space.

Which of the section sizing behavior is used is dependent on the chosen page type. For each of the page types
described in the sections below, we present the typical layouts, and the way that the sections are sized.

Card and Document page layouts


The primary purpose of Card pages is to support users managing master and reference data, such as Customer,
Vendor, and Item entities. (The name Card refers to how this kind of business data was kept on paper cards in
filing cabinets before being computerized.) The Card page type is also often used for setup pages.
The Document pages' primary purpose is to represent a transaction or other important event in the domain of
business. Document pages are the computerized counterpart to paper-based documents (quotes, invoices,
orders, etc.), and as such, document pages often have associated workflow or audit trail requirements.
Below are examples of Card and Document page compositions, showing how space is divided. Parts can be
combined in more ways than shown here to suit different scenarios.
Card layouts
EXA M P L E 1 EXA M P L E 2 EXA M P L E 3

Sections are placed vertically from top A ListPart can be embedded. In this When a ListPart is embedded as the
to bottom of the page. case, the ListPart's height is limited. last part on the page, it will expand to
fill space.

Document layouts
EXA M P L E 1 EXA M P L E 2 EXA M P L E 3

Sections are placed vertically from top Multiple ListParts can be embedded. In When no ListPart is embedded, the
to bottom of the page. The lines this case, the first ListPart is allowed Document layout follows the Card
ListPart comes after the header the most space. layout exactly.
section(s).
EXA M P L E 1 EXA M P L E 2 EXA M P L E 3

NOTE
The Document page type allows the first ListPart on the page to use additional vertical space before showing a scrollbar.
This allows more space for showing the document lines without requiring the user to scroll.

The well-designed card or document page


From the user's perspective, the following are qualities of a well-designed card or document page:
Uses the page type Card if the page represents master or reference data, or is a setup page.
Uses the page type Document if the page represents a transaction or other important event in the domain of
business.
Has a page title that clearly identifies the data represented in the page.
Is optimized for overview by organizing data in FastTabs and marking relevant fields as Promoted or
Additional .
Favors header fields and other important fields by placing them in a FastTab titled General that come first on
the page.
Has one or two FactBoxes to give relevant statistics and quick access to related documents.
For Document pages, a FastTab titled Lines comes second on the page with the document lines.
Doesn't include a repeater control, unless the repeater control is in a ListPart page that's embedded in
the page.

ListPlus page layouts


The ListPlus pages' primary purpose is to support users in managing or browsing a collection of data, or entries,
related to a specific business entity or event. For example, the Customer Sales page is a ListPlus page that shows
sales numbers for a customer and providing dedicated viewing options for sales analysis.
The ListPlus page type is a versatile means to support analysis and management tasks in a specific entity context
(named by the page title). ListPlus pages can show persistent data about the entity/event in addition to giving
options for how data is viewed or filtered.
A ListPlus page should generally not contain a repeater control but will typically embed a ListPart page that in
turn embeds a repeater. In addition, a ListPlus page can embed groups of fields and CardParts. Below are
examples of ListPlus page compositions, showing how space is divided. Parts can be combined in more ways
than shown here to suit different scenarios.
EXA M P L E 1 EXA M P L E 2 EXA M P L E 3

Page sections are placed from top to When placing two or more ListParts, When placing two ListParts in a group,
bottom. The first ListPart fills vertical they'll share available vertical space. they share horizontal space.
space.

From the user's perspective, the following are qualities of a well-designed ListPlus page:
Has a page title that clearly identifies the context for the information presented in the page.
Is optimized for showing one set of details, and giving the user means to work with them.
Presents information in the page in such a way that the hierarchy can be understood when read from top to
bottom.
If present, fields that control which data is presented in another FastTab come before that FastTab.
If present, fields that show data dependent on the chosen row (in the ListPart) come after the ListPart.

List page layouts


List pages support users viewing and finding specific entities or entries in a collection. Lists that are editable
have cells available for data entry and update.
List pages must contain a single Repeater group. In addition, a list can embed groups of fields, card parts, and
list parts. Below are examples of list page compositions, showing how space is divided. Parts can be combined in
more ways than shown here to suit different scenarios.

EXA M P L E 1 EXA M P L E 2 EXA M P L E 3

The repeater control assumes full When a field group or cardpart is When a listpart is embedded, space is
vertical space. embedded, space for repeater is shared equally between part and
reduced. repeater.
From the user's perspective, the following are qualities of a well-designed List page:
Defines a set of columns that is optimized for viewing and filtering the given collection. Optimize the column
order for data entry if the list is editable.
Has a page title that clearly names or identifies the collection of entities/entries presented.
If a summary or more detail related to the selected row are shown, these appear below the list.
If custom viewing options are available, these appear above the list.
Has one or two FactBoxes to give essential collection statistics, and relevant related details for the selected
row.

Worksheet page layouts


A Worksheet page lets users view and manage a collection of entries in tabular or matrix form. It's well suited
for cases when a custom filter or a set of default field values is the basis for users' understanding of the
collection, such as with journals (where the user selects a batch) and inquiry pages (where the user forms a
query).
Use a Worksheet page (instead of a List page) when there are header fields that determine or subdivide a
collection, that is, the user must make a choice in the header field before the repeater has data to show at all. Or
when there are header fields that represent default values for data entry in the repeater.

NOTE
The Worksheet page type doesn't support the same part and group compositions as the List page type.

Worksheet pages must contain a single Repeater group. In addition, a worksheet can embed groups of fields,
CardParts, and ListParts. Below are examples of list page compositions, showing how space is divided. Parts can
be combined in more ways than shown here to suit different scenarios.

EXA M P L E 1 EXA M P L E 2 EXA M P L E 3

The repeater control takes full vertical A group, CardPart, or ListPart can be Groups and/or parts are embedded
space, but leaving space for a group or embedded below the repeater that above and below, leaving the
CardPart above. then assumes the remaining vertical remaining vertical space for the
space. repeater.

From the user's perspective, the following are qualities of a well-designed worksheet page:
Defines a set of columns that is optimized for overviewing and managing the given collection. Columns are
ordered relative to their importance.
Has fields above the grid that specify filtering options or specify the default values effective during data entry
and editing in the grid.
If summary fields or more details of the selected row are shown, these appear below the repeater.

Dialog page layouts


Some page types in Business Central are available exclusively for displaying dialogs, such as the StandardDialog
and ConfirmationDialog page types. In addition, there are programmatic ways in AL to display a dialog to the
user with the Dialog data type, and dialogs defined as report request pages.
It's also possible to use the common page types ( Card , Document , List , etc.) to present a dialog to the user. In
this case, pages are created, composed, and can embed the same elements, as when displayed ordinarily.
Presenting the page to the user as a dialog requires certain AL code that activates the dialog mode. When this
happens, the page is shown with dismiss buttons in the page footer.

Generally, Business Central displays dialogs on the screen in a frame that is more narrow and not taking up full
vertical height, compared to how pages appear ordinarily. Aside from that, pages lay out their contents
according to the same principles, whether displayed as a dialog or not.
Given the size of the screen where the dialog appears, more or less of the page contents will be visible without
scrolling. When a page contains much content, it's possible for the user to increase the dialog size with the
maximize button.

NOTE
The dialogs created from the ConfirmationDialog and StandardDialog page types are not currently providing a maximize
button.

See Also
Page, Page Fields, and Page Extension Properties
PageType Property
Actions Overview
Using Designer
Adding a FactBox to a Page
Designing Role Centers
Designing List Pages
2/6/2023 • 8 minutes to read • Edit Online

The List page type displays records from an underlying table, either as rows and columns or as individual tiles.
Overview
Structure
Behavior points
Developer tips
Designing for devices

You design list pages when you want to provide users with a collection of data, enabling them to get an
overview of and find entities to work with, such as customers, vendors, or sales orders. Typically, a list page will
link to an associated card page that lets users view or modify specific entities in the list.
There are different ways to incorporate a list page into that application:
Make the list page available from the navigation of a Role Center page.
This gives users quick access to the page. With this implementation, the list page opens in the content
area of the Role Center page, where the Role Center's navigation area is still present and accessible at the
top of the page. For more information about Role Centers, see Designing Role Centers.
Make the list page available from an action on another page.
With this implementation, the list page opens in a separate window in front of the current page.
Make the list page searchable from the Tell me what you want to do feature.
With this implementation, the list page also opens in a separate window. For more information, see
Adding Pages and Reports to Search.
Customizing a list pages from the client
In the client, users can personalize list pages by rearranging or hiding records or FactBoxes as they like. For
more information, see Personalizing Your Workspace.
As a developer or administrator, you can use Designer to customize the list page the same way that individual
users personalize their own work spaces. The difference is that changes you make are applied to all users. For
more information, see Using Designer.
Simple List Page Code Example
2/6/2023 • 2 minutes to read • Edit Online

The AL code in this article creates a simple list page that displays records from an existing table.

For a more detailed explanation of the list page, see Designing List Pages.

page 50111 SampleCustomerList


{
PageType = List;
ApplicationArea = All;

// Specifies the page to display records from the Customer table.


SourceTable = Customer;

// Makes the page searchable from the Tell me what you want to do feature.
UsageCategory = Lists;

// Specifies the card page Sample Customers to be uses for modifying or creating new customer records.
CardPageId = 50112;

// Sets the title of the page to Sample Customers.


Caption = 'Sample Customers';

layout
{
area(Content)
{
// Sets the No., Name, Contact, and Phone No. fields in the Customer table to be displayed as
columns in the list.
repeater(Group)
{
field("No."; "No.")
{
ApplicationArea = All;

}
field(Name; Name)
{
ApplicationArea = All;

}
field(Contact; Contact)
{
ApplicationArea = All;
}
field(Phone; "Phone No.")
{
ApplicationArea = All;

}
}
}

actions
{
// Adds an action on the Actions menu of the action bar that opens the page Customer Ledger Entries.
area(Processing)
{
action("Ledger Entries")
{
ApplicationArea = All;
RunObject = page "Customer Ledger Entries";
trigger OnAction();
begin

end;
}
}

// Promotes an action for creating a sales quote to promoted action menu called New.
area(Creation)
{
action("New Sales Quote")
{
ApplicationArea = All;
RunObject = page "Sales Quote";
Promoted = true;
PromotedCategory = New;
Image = NewSalesQuote;
trigger OnAction();
begin

end;
}
}

// Adds an action on the Report menu that opens the Top 10 List report.
area(Reporting)
{
action("Top 10 List")
{
ApplicationArea = All;
RunObject = report "Customer - Top 10 List";
trigger OnAction();
begin

end;
}
}
}
}

See Also
AL Development Environment
Page Extension Object
Actions Overview
Adding Pages and Reports to Tell Me
Personalizing Your Workspace
Using Designer
Working with Repeater Controls
2/6/2023 • 4 minutes to read • Edit Online

A repeater control is used to define a list of records from the source table of a page. Records are displayed as
rows and columns, where each row is a record and each column is a field.
You add a repeater() control within the area(Content) control of a page, and then you nest a field() control
for each of the fields from the table specified in the SourceTable Property that you want to include. The order of
the field controls determines the order in which they appear on the page.
A list is a characteristic element of the layout of pages of the type List and ListPar t . You define the type of a
page using the PageType Property. List pages are designed for using a single repeater() control, which must be
defined at the beginning of the content area. If you include more than one repeater or another control like a
group or grid, the page might not behave as expected. If you want to design a page that includes controls in the
content area other than a repeater, then try using a Worksheet page type instead. For more information, see
Pages Types and Layout.
Pages of the type API are also designed to integrate a repeater control, but they can't be displayed in the user
interface.
The following figure illustrates how a list created by a repeater is displayed in the Web Client.

Limitations
The Web client doesn't support displaying repeater controls that contain other Parts or FlowFilter fields.
The repeater control is only supported by the Web client in collection-oriented pages List, Worksheet, and
ListPart. The repeater control isn't supported on entity-oriented page types, like Card , CardPart , Document ,
or Navigation . In fact, if you use a repeater on an entity-oriented page, you'll get UICop Warning AW0008. If
you want to include data as a list on one of these page type, create a ListPart page that contains repeater
control, and then use the ListPart in the entity-oriented page.

How to customize a list


You can make various changes to customize the appearance of the list in a page and determine which data is
displayed. The changes can be done using AL code or directly from the Web Client.
To improve the visibility and readability of the list, you can set some properties at control and field level. For
example, you can specify the width of a column using the Width Property. Or, you could set row indentation
using the IndentationColumn Property and IndentationControls Property.
You should also consider limiting the number of columns and enabling a freeze column by setting the
FreezeColumn Property. Apply filters to display only the most relevant data and minimize scrolling. This practice
is important when it comes to mobile devices, where there are restrictions as to how much content can be
shown. You can also limit data and scrolling by defining a new view on a page. For more information, go to
Views.
Some other alternative things you can do include:
Add, move, or hide fields and make adjustments like modifying the column width, directly from the user
interface.
To apply these changes, use the Designer tool. Go to Using Designer. If these changes are meant for your
own workspace, then you use the Personalize tool. For more information, see Personalizing Your
Workspace.
Use the filter pane from the page to sort the data and apply filters. Go to Sorting, Searching, and Filtering.
Use the Tile View to display records as tiles (or bricks) instead of as rows and optimize the space and
readability of data. For more information on how to customize the tile view, see Displaying Data as Tiles.

Example
The following example shows how the repeater control is used to define a list page for the Customer table.
page 50111 SampleCustomerList
{
PageType = List;
ApplicationArea = All;
SourceTable = Customer;
UsageCategory = Lists;
CardPageId = 50112;
Caption = 'Sample Customers';

layout
{
area(Content)
{
// Sets the No., Name, Contact, and Phone No. fields in the Customer table to be displayed as
columns in the list.
repeater(Group)
{
field("No."; "No.")
{
ApplicationArea = All;

}
field(Name; Name)
{
ApplicationArea = All;

}
field(Contact; Contact)
{
ApplicationArea = All;
}

field(Phone; "Phone No.")


{
ApplicationArea = All;

}
}
}
}

actions
{
area(Processing)
{
action("Ledger Entries")
{
ApplicationArea = All;
RunObject = page "Customer Ledger Entries";
trigger OnAction();
begin

end;
}
}
}

You can use page customizations to modify the layout of a page for concrete users. The following code hides the
"Phone No." column from the users with Accountant profile.
profile Accountant
{
Description = 'Functionality for finance staff performing any AR or AP work and managerial reporting.';
RoleCenter = "Accountant Role Center";
Customizations = MyCustomization;
}

pagecustomization MyCustomization customizes "Customer List"


{
layout
{
modify("Phone No.")
{
Visible = false;
}
}
}

See Also
Pages Overview
Designing List Pages
Page Customization Object
Displaying Data as Tiles for Lists
2/6/2023 • 4 minutes to read • Edit Online

In the client, on List type pages, users can view the page in the tile view. The tile view shows records as tiles (or
bricks) instead of as rows. Tiles optimize space and readability of data. Tiles are especially useful for images, like
on a page that show items, customers, and contacts. Business Central also provides Microsoft Teams integration,
which enables users to display an interactive, visual representation of records in a Teams chat. These features
both use the same design concept, which is based on defining a Brick field group on the entity's source table.
By default, the tile view will display the first five fields that are defined in page's repeater control. This article
describes how you can customize the tile view for list type pages.

NOTE
The Brick field group is also used to define the fields that appear when a record is shown in a Microsoft Teams
conversation. For more information, see Extending Teams Cards.

Tile view in the client


To switch between the list and tile view, users selecting the View layout options icon in the action bar of the
page. If tiles contain a media field type, then there are two tile view options: Tiles and Tall Tiles . The same
information is displayed except with Tall Tiles , images are larger and display at the top of the tiles.
Tiles are interactive. A context menu is available in the upper right corner. The context menu contains the actions
that are defined for the record, like in the list view. To drill down to a card page for a record, the user selects the
tile.

Customizing the tile view in AL


You specify the data that you want shown in the tile view in the source table of the page by adding a
Field Group that has the name Brick . The following code illustrates the syntax, but it will depend on the fields
you want to display:

fieldgroups
{
fieldgroup(Brick; <field 1>, <field 2>, <field 3>, <field 4>, <field 5 >, <image field>, <verbose
text field>
{

}
}

There's no limit on the number of fields you can display in a tile. However, we recommend that you limit tiles to
five data fields and one image field.

IMPORTANT
By default, the Field Group named DropDown is interpreted as Brick when a Brick definition has not been set. The
DropDown is typically set on entities such as customer, vendor, and items. For more information, see Field Groups (Drop-
Down Controls).
Field layout in tiles
The order of the fields determines how they appear in the layout of the tile, no matter the order in the page
object. Depending on the number of columns that you define in the Field Group , the layout will dynamically
change. This concept is illustrated in the following figure:

T IL E TA L L T IL E

Field 1 appears in small font in its own row of the tile.


Fields 2 and 3 are shown in a large font and appear in the same row under primary field 1. These fields
should typically contain data that identifies the brick. For example, in the Customers list, the Customer
Name and Balance are displayed in fields 2 and 3.
Remaining fields appear in rows of two.
A verbose field appears at the bottom of the tile, separated by a line.
Including images in tiles
To display an image in the brick, you include a Media data type field in the Field Group definition. You don't
have to include a field control for the media field in the page object, because the image will be shown in the tile
view automatically.
The image will be displayed on the left side of the tile or at the top in the Tall Tiles view, no matter what its
position is in the Field Group definition. As long as you're don't want a verbose text field, you can position the
image field anywhere in the Field Group definition. If an image doesn't exist for a certain record, a default
picture is displayed instead.
For information including media on records, see Working With Media on Records.
Styling text in tiles
Like the list view, the tile view supports the Style Property and StyleExpr Property. You apply these properties on
the page field controls. These properties, for example, let you mark numbers as favorable or unfavorable.
Verbose text in tiles
When records are best represented by a longer, more descriptive text, you can design tiles to display verbose
text. To display verbose text, the following requirements must be met:
The field must be a text field and the size greater than or equal to 100 characters
The field is added as the last field in the Field Group definition, but can't be in the first, second, or third
position.
On the rendered tile in the UI, the field must be appear on the left side of the tile.
If these conditions are met, the tile expands to display the field in up to three rows of text.

Example
The following code is a simple example of a table that includes Field Group control for displaying data in the
tile view of a list page. The following figure illustrates how a tall tile with an image will appear on the page.

Table 50100 MyTable


{

fields
{
field(1; Number; Integer)
{
}

field(2; Description; Text[50])


{
}
field(3; Inventory; Integer)
{
}
field(4; Image; Media)
{
}
field(5; DescriptionLong; Text[100])
{
}
}

keys
{
key(PK; Number)
{
}
}

fieldgroups
{
fieldgroup(Brick; Number, Description, Inventory, Image, DescriptionLong)
{
}
}
}
}

page 50100 MyListPage


{
PageType = List;
ApplicationArea = All;
UsageCategory = Lists;
SourceTable = BrickTableTest;
Editable = true;
CardPageId = MyCardPage;

layout
{
area(Content)
{
repeater(GroupName)
{
field(Number; Number)
{
ApplicationArea = All;
}
field(Description; Description)
{
ApplicationArea = All;
}
field(Inventory; Inventory)
{
ApplicationArea = All;
Style = Attention;
}
field(DescriptionLong; DescriptionLong)
{
ApplicationArea = All;
}
}
}
}
}

See Also
Designing List Pages
Working With Media on Records
Views
2/6/2023 • 4 minutes to read • Edit Online

Views in Dynamics 365 Business Central are used on list pages to define a different view of the data on a given
page. Views can be defined for Pages, Page Extensions, and Page Customization. Views are defined on page
extension objects to provide an alternative view of data and/or layout on an existing page. In views on page
customization objects, they can be used to provide an alternative view for a certain profile.
A view offers:
Filtering on multiple table fields on the source table defined for the page.
Sorting of the data on multiple table fields, but only in one direction; either ascending or descending.
Layout changes, modifying page columns, moving them, etc.
Views are defined directly in code, on the list page that they modify. The defined view or views are available to
the user through Filter Pane on a page and appear in the sequence that they're defined in code.

NOTE
allowDebugging does not apply to views. Views defined in an extension with allowDebugging set to false can still
be copied using Designer.

Snippet support
Typing the shortcut tview will create the basic layout for a view when using the AL Language extension in
Visual Studio Code.

Filtering and sorting


You can filter on the data in a view by using the Filters property. The following code is an example of the
syntax:

Filters = where ("Balance (LCY)" = filter (> 500), Name = filter ('G*'));

For more information, see Filters.


You can sort on the data in a view by using the OrderBy property. The following code is an example of the
syntax:

OrderBy = ascending ("Balance (LCY)", Name);

For more information, see OrderBy.

NOTE
All filters are applied to the table field(s), not the page field(s), which allows filtering on a table field not shown on the
page.
Layout changes
By default, a view will have the same field layout as the page's All view, which means it will show the same
columns, in the same order, with the same widths. The layout will also have the same freeze column. This
behavior is a basic experience in the case where defining a specific layout for the view isn't important. It's
controlled by the SharedLayout property on the page view, which in this case is set to true . This layout is
referred to as a shared layout view . The following example code illustrates a shared layout view :

view(SharedLayoutView)

{
// This view only define filters, but no specific layout.
// User personalization are applied on this view.
Caption = 'View With Shared Layout';
Filters = where ("Balance (LCY)" = filter (> 500), Name = filter ('G*'));
}

By contrast, you set the SharedLayout to false to design a unique layout view that defines its own layout and is
independent from all other views. Any changes coded in the layout section are applied in the view. User
personalizations made on the page aren't applied on the view. For example:

view(UniqueView)
{
Caption = 'View With Unique Layout';
Filters = where ("Balance (LCY)" = filter (> 500), Name = filter ('G*'));
// By settings this property to false, the view gets its own independent layout.
// User personalization are not applied on this view.
// Instead, the layout defined below is applied.
SharedLayout = false;

layout
{
movefirst(Control1; "Balance Due (LCY)")
}
}

IMPORTANT
SharedLayout must be set to false to use a custom layout on the view (the layout section). A compiler error is
reported otherwise.

View example
The following example shows a page customization of the Customer List page, which is available for a specific
role center only; the My Role Center . Change the role center view under My Settings . The definition of the
view adds a caption that's displayed on the left side in the UI. The view sorts the customer balance in ascending
mode and the view modifies the layout by moving the customer balance first and adding a freeze column after
it.

IMPORTANT
The definition of the view section must come after any definition of layout and actions, otherwise you will get a compiler
error AL0577.
profile MyProfile
{
Caption = 'My Role Center';
RoleCenter = "Order Processor Role Center";
Customizations = MyCustomization;
}

pagecustomization MyCustomization customizes "Customer List"


{
layout
{
// Change the layout of the page
}

actions
{
// Add any actions to the page
}

views
{
addfirst
{
view(BalanceLCY)
{
Caption = 'Ordered Balance LCY';
OrderBy = ascending ("Balance (LCY)");
Filters = where ("Balance (LCY)" = filter (> 500), Name = filter ('G*'));
SharedLayout = false;

layout
{
// Change the layout of the view

movefirst(Control1; "Balance (LCY)")

modify(Control1)
{
FreezeColumn = "Balance (LCY)";

}
}
}
}
}

Limitations
In general, views can in several ways be compared to page customizations. Here are the limitations of views:
For views, you can modify the same control properties as for page customization objects independently of
where the view has been defined (page, page extension, or page customization level). This condition is
validated by the compiler.
It isn't possible to use variables or methods in a view. When writing client-side expressions for properties like
Visibility , it will only be possible to use constant values or table field references. This condition is validated
by the compiler.
It isn't possible to create new controls for a page from a view.

See Also
AL Development Environment
Developing Extensions
Page Object
Page Extension Object
Page Customization Object
SharedLayout Property
Migrating from Legacy Views to Modern Views
2/6/2023 • 4 minutes to read • Edit Online

IMPORTANT
Legacy views have been deprecated and will be removed in Business Central 2023 release wave 2 (version 23). You can
experience this change already in 2022 release wave 2 (version 21) by enabling Legacy list views are hidden on the
Feature Management page. Learn more at Enabling Upcoming Features Ahead of Time.

Modern views were introduced with Business Central April 2019 release wave and are the recommended design
going forward. Legacy views are list views that were created by developers in previous versions of Business
Central by placing them on the Role Center page object. Business Central displays legacy views side by side with
modern views directly on the list page. But legacy views offer a degraded experience and fewer options
compared to modern views.

How can developers migrate to modern views?


If your solution or customizations use legacy views, it's recommended you migrate your code to modern views
before any environments are upgraded to version 23. To plan your approach, consider that legacy views
originate from two distinct sources:
1. Role center actions
These actions are defined in the area(sections) , area(embedding) , and area(processing) sections of the
code. The actions run a list page and specify filters or sorting by using the RunPageView. Developers
must remove legacy views from role center page code, and reimplement them as modern views on the
target list page instead.
The following code illustrates the AL code pattern on role center pages to look for and replace:

actions
{
area(sections|embedding|processing)
{
action(<action_name>)
{
Caption = '<page_caption>';
RunObject = Page "<page_name>";
RunPageView = <filters_and_sorting>;

For example, here's a code snippet of a role center page action that adds a legacy view on the Sales
Order List page:
actions
{
area(embedding)
{
action(SalesOrdersShptNotInv)
{
Caption = 'Shipped Not Invoiced';
RunObject = Page "Sales Order List";
RunPageView = WHERE("Shipped Not Invoiced" = CONST(true));
}

2. Role Center cue tiles


When you add a cue to a Role Center and the cue's value is based on a filtered list, a view based on the
filters is automatically included on the list page. This behavior is done for backwards compatibility
purposes. For example, a cue on the Sales Order Processor role center that displays delayed orders
will also display a legacy view named Delayed on the Sales Orders list page. Microsoft will remove
backward compatibility with version 23. If these automatically created views are valuable, we recommend
developers implement them as modern views on the target list page.
The following code illustrates the AL code pattern that creates legacy views for role center cues. For more
information about cues, see Creating Cues on Role Centers.

table <ID> "<cue_table_name>"


{
fields
{
field(5; <cue_data_field>; Integer)
{
// Filters that make up the view on the drill-down page
CalcFormula = Count("<source_table>" WHERE(<filters>));
}

page <ID> "<role_cue_page_part>"


{
SourceTable = "<cue_table_name>";

layout
{
area(content)
{
cuegroup("<cue_group_name>")
{
field(<cue_data_field>; Rec.<cue_data_field>)
{
// List page that opens from cue
DrillDownPageID = "<list page>";
}

Once you've identified the source of a legacy view, the next step is to recreate it as a modern view, as described
at Views.

Can end-users benefit from modern capabilities before developers


migrate legacy views?
Users can overcome limitations of legacy views simply by using the Save as... option to save a copy of the
legacy view as a modern, personal view. Similarly, administrators can customize a user role and save the legacy
view as a new role-specific view. While this method is quick and practical, it duplicates views on the list page,
and doesn't convert the legacy view.

Why switch to modern views?


Benefits for developers:
Benefit from a more declarative model where the view is implemented directly on the list page that it filters.
Add the view only once, instead of having to add it to all Role Center pages that happen to navigate to the list
page, while still being able to define role-specific views.
Opportunity to define a unique column layout per view.
Developers benefit from future enhancements to views.
Benefits for end-users:
Users will be able to personalize their workspace by hiding, showing, and reordering these views in the
Filter pane. Similarly, this task can be done once for all users of a particular role.
The user experience is simple and consistent when the list page doesn't contain a mix of legacy and modern
views, and performance is improved slightly.
Users receive a consistent choice of views no matter how they navigate to the list page: from the Role Center
navigation menu, by searching for the page, through a browser favorite or shared link, or on other form
factors.
Customers benefit from future enhancements to working with views.

See Also
List Views FAQ
Business Central April '19 release plans - List Views
Business Central April '19 release plans - Save and personalize list views
AL Development Environment
Developing Extensions
Adding Custom Filter Tokens
2/6/2023 • 3 minutes to read • Edit Online

In the client, when filtering lists using the filter pane, users can enter filter tokens, which are special words that
resolve to one or more values. This powerful feature makes filtering easier by reducing the need to navigate to
other pages to look up values to enter as filter criteria.
There are several useful filter tokens available in Business Central. For example, entering %mycustomers in a
Customer No. field will resolve to the set of customers in the user's My Customers list such as 1001|1002 ,
making it easy to find relevant sales orders for customers 1001 and 1002.
You can add custom filter tokens and make these available in any language and across the application. To add
your custom filter token, you need to define the token word that users will enter as filter criteria, and define a
handler that resolves the token to a concrete value at runtime. For more information, see Filter Tokens in our
ALAppExtensions repository on GitHub.

Defining the token word and the handler


To create the token word, start by defining a multi-language text string for your word. Subscribe to the
OnResolveTextFilterToken event associated with the MakeTextFilter method from the Filter Tokens codeunit.
In the event subscriber, if the value of the TextToken parameter contains the token string, process its value and
construct the final filter string. If the filter string must contain multiple values, you must handle the operators
that join them by adding the | filter symbol (OR operation). Complete the operation by setting the value of the
TextFilter parameter to the value of the final filter string.

TIP
Filter criteria will often contain symbols along with filter tokens. We recommend that you only modify the filter token you
have introduced and preserve the rest of the filter string.

Example
This example shows how you can use the guidelines above to create the %MYTOKEN filter token. This will
return a filter with the accounts marked as favorite by the user.

NOTE
To keep this sample short and simple, the entire filter string is overwritten.
codeunit 50101 MyAccountFilterTokenSimple
{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Filter Tokens", 'OnResolveTextFilterToken', '', true,
true)]
local procedure FilterMyAccounts(TextToken: Text; var TextFilter: Text; var Handled: Boolean)
var
MyAccount: Record "My Account";
MaxCount: Integer;
begin
if StrLen(TextToken) < 3 then
exit;

if StrPos(UpperCase('MYTOKEN'), UpperCase(TextToken)) = 0 then


exit;

Handled := true;

MaxCount := 20;
MyAccount.SetRange("User ID", UserId());

if MyAccount.FindSet() then begin


MaxCount -= 1;
TextFilter := MyAccount."Account No.";

if MyAccount.Next() <> 0 then


repeat
MaxCount -= 1;
TextFilter += '|' + MyAccount."Account No.";
until (MyAccount.Next() = 0) or (MaxCount <= 0);
end;
end;

To try it out in the client, open the Charts of Accounts page, filter on No. field, and type in a substring that
starts the same way with the chosen token word, like %MYTO .

Design considerations
Resolving tokens is intended to be fast, simple, and reliable. When implementing event subscribers to resolve
filter tokens, keep in mind that these events can be triggered from any user task in Business Central, and in
some cases may be triggered repeatedly such as when searching across columns. To improve usability and
reduce the impact on performance, do consider the following practices:
Avoid implementing tokens that are only relevant to few business tasks, or assume they are used in the
context of a specific page.
Avoid implementing tokens that are time-consuming to resolve. Examples of this include looking up records
in large or poorly indexed tables, or fetching data from a remote service.
Avoid implementing tokens that are complex or unreliable and may result in error.
Avoid displaying pages, dialogs or any other form of interactive UI.

See Also
Sorting, Searching and Filtering Lists
Designing Indented Hierarchy Lists
2/6/2023 • 4 minutes to read • Edit Online

This article explains how to indent specific rows in a list.

Overview
Using the indentation properties in AL, you can display rows in a parent-child structure.

A row that's indented from a row above is considered a child of that row. The row above is considered the
parent. Indenting rows can help organize related records in the list and make it more readable for the user.
You can display indented hierarchy lists on any page type, including List pages, Worksheets, and ListParts. Pages
can also be editable.
There are two kinds of indented hierarchy lists: fixed and collapsible. In a fixed hierarchy, rows that are indented
are always shown. In a collapsible, users can collapse and expand parent rows to show and hide child records.

Setting up a fixed indented hierarchy


In a fixed hierarchy, child rows are always shown, as illustrated in the following figure.

In the figure, indentation is applied to the second column. Setting up the fixed indented hierarchy involves
configuring two properties on the page object: IndentColumn and IndentationControls.
The IndentationColumn Property determines which records get indented and by how much. You set the
property to either a field in the page's source table or to a variable. The important thing, is that property
resolves to an integer. This integer determines the indentation level.
The IndentationControls property specifies which column in the list gets indented. You can only specify
one column.
Example
In this example, you indent records based on the value of the Indent column and apply the indentation to
Name column. You set the IndentationColumn and IndentationControls on the repeater of the page, as shown in
the following code:
page 50100 MyPage
{
PageType = List;
ApplicationArea = All;
UsageCategory = Lists;
SourceTable = MyTable;
Editable = true;

layout
{
area(Content)
{
repeater(Control1)
{
IndentationColumn = Indent;// IndentationColumn = IndentVariable;
IndentationControls = Name;

field(Number; Number)
{
}
field(Name; Name)
{
}
field(Indent; Indent)
{
}
}
}
}

//trigger OnAfterGetRecord()
//begin
//IndentVariable := Indent;
//end;

//var
//IndentVariable: Integer;
}

You can achieve the same results using a variable instead of the table field for the IndentationColumn property.
Look at the commented lines of code in the example above.
For a more detailed implementation example, see the Chart of Accounts page in the base application (link
requires sign-in to Business Central online).

Setting up a collapsible indented hierarchy


In a collapsible hierarchy, users can collapse and expand parent rows to show and hide child records.

Setting up a collapsible hierarchy is similar to the fixed indented list, except for the properties that you set. A
collapsible hierarchy involves three properties: IndentColumn, ShowsAsTree, and TreeInitialState.
Like in fixed indented hierarchy, the IndentationColumn Property is an integer data type field or variable that
determines which records get indented and by how much.
The ShowAsTree Property makes the hierarchy collapsible.
The TreeInitialState Property, which is optional, specifies whether the list is collapsed or expanded when the
page opens.
Unlike fixed indented lists, a collapsible hierarchy always indents the left-most visible column in the repeater. The
IndentationControls property is ignored. If users customize the page by moving another column first, the moved
column will be indented instead.
Example
In this example, you'll indent records based on the value of the Indent column. Records will indent on the
Number column and parent records will be collapsible. You add the IndentationColumn, ShowAsTree, and
TreeInitialState properties to the pages' repeater:

page 50100 MyPage


{
PageType = List;
ApplicationArea = All;
UsageCategory = Lists;
SourceTable = MyTable;
Editable = true;

layout
{
area(Content)
{
repeater(Control1)
{
IndentationColumn = Indent; // IndentationColumn = IndentVariable;
ShowAsTree = true;
TreeInitialState = CollapseAll;

field(Number; Number)
{
}
field(Name; Name)
{
}
field(Indent; Indent)
{
}
}
}
}

//trigger OnAfterGetRecord()
//begin
//IndentVariable := Indent;
//end;

//var
//IndentVariable: Integer;
}

You can achieve the same results using a variable instead of the table field for the IndentationColumn property.
Look at the commented lines of code in the example above.
For a more detailed implementation example, see the Assisted Setup page in the base application (link requires
sign-in to Business Central online).
Collapsed or Expanded lists
Users can change whether the page opens with rows collapsed or expanded, essentially overriding the
TreeInitialState property. They change the behavior by selecting the Toggle Expand All / Collapse All button
in the header of the first column, or using the button in the top-left corner of the repeater. It stays this way, until
they delete personalization on the page.

Design and behavior considerations


When using an indented hierarchy, consider the following behavior:
When indentation is specified, it's no longer possible to use sorting on the columns in the repeater control or
display the list as tiles.
Right-aligned data in columns, such as the integer data type, won't appear as indented.
Indentation is used to visually communicate structure, without modifying the table of records itself. There's
no tightly defined parent-child relationship between records, so you must implement additional logic if
records need to relate together. For example, if a user deletes a parent record, Business Central won't delete
all of its child records.
Indenting records in a list doesn't automatically apply any additional styling to emphasize parent records and
distinguish them from child records. You can implement styling using style expressions. For example, you
could format all fields on parent records to display bold values. Learn more about StyleExpr Property.

See Also
IndentationColumn Property
IndentationControls Property
ShowAsTree Property
TreeInitialState Property
Page and Page Extension Properties
Teaching tips and in-app tours for onboarding users
2/6/2023 • 9 minutes to read • Edit Online

A key element in educating users about Business Central pages and concepts is the tour. A tour is a sequence of
teaching tips.
Teaching tips can be defined at the page level, the page teaching tip, and be followed by teaching tips at the
control level, the control teaching tips. Both types of teaching tips are defined by the .AL properties AboutTitle
and AboutText , and an extension can overwrite teaching tips in the default version.

Page teaching tips


The primary purpose is to increase the user's chance of success with the page. So, the title and
description of the page teaching tip should answer the following hypothetical user questions:
AboutTitle : What is this page about?
AboutText : What can I do with this page?
Teaching tips explain Business Central logic that is relevant to the page.
Teaching tips let users discover and initiate the related tour whenever they are ready for it.
Allow users to get on with a task right away without blocking them.
A teaching tip can be defined for any page in Business Central, except the role centers, dialogs, and
request pages for reports.
After users dismiss a teaching tip and tour, they can choose or hover over the page title. This action will
reopen the teaching tip, and the user can retake the tour, for example.
On a page that is opened from the checklist, the tour is considered an invited tour, and the page teaching
tip has a Go back button that takes the user back to the checklist.
The following illustration shows a page teaching tip that explains what the page is about and can invite the user
to take a tour. The teaching tip renders in the lower left corner.

The following illustration shows how choosing the page title will reopen the teaching tip so that the user can
retake the tour.
How to write page teaching tips
There are different rules for teaching tips for lists versus cards and documents.

L IST PA GE W IT H T EA C H IN G T IP C A RD PA GE W IT H T EA C H IN G T IP

AboutTitle : About sales invoices AboutTitle : About sales invoice details


AboutText : Sales invoices appear in this list until they're AboutText : You can update and add to the sales invoice
finalized and posted. After an invoice is posted, find it again until you post it. If you leave the invoice without posting,
in the Posted Sales Invoices list. you can return to it later from the list of ongoing invoices.

Answers the following questions: Answers the following questions:

What can I do on this page in general? What can I do on this page with this particular field
or action?
Is there a related entity I should know about?
What is the desired outcome of the task in this page?
The title for a list page teaching tip will typically use
the plural form, such as About sales invoices The title for a card or document page teaching tip will
typically be [entity name] + details, such as About
sales invoice details

What you should know about tours


Tours are sequential teaching tips describing functionality while pointing to elements in the UI.
The tour guides the user around the page.
Tours can be initiated from the page teaching tip
During a tour, a page with input fields will be in read mode.
Tours show where to find something, what it is, what it means, what you can do with it, and what it
affects.
A control teaching tip can point out a value that the user must check to know their next step.
Example: The Status field on an invoice. When the status is open, the user can edit the invoice.
A control teaching tip can describe the relevant timing for when to use a field or action.
Example: The Post action: When done editing, then post and send.

How to write teaching tips for controls


There are different rules for teaching tips for input fields and actions.

T EA C H IN G T IP P O IN T IN G TO A N IN P UT F IEL D T EA C H IN G T IP P O IN T IN G TO A N A C T IO N

AboutTitle: Who you are selling to Content example for the Post action:
AboutText: This can be an existing customer, or you can AboutTitle: When all is set, you post
register a new from here. Customers can have special prices AboutText: After entering the sales lines and other
and discounts that are automatically used when you enter information, you post the invoice to make it count. After
the sales lines. posting, the sales invoice is moved to the Posted Sales
Invoices list.

The teaching tip can point to a field that may or may With multiple similar actions,such as Post and Post
not have data. & New , call out the simplest version only.

A control teaching tip can explain an important Avoid action language that tells users to do
value's meaning, such as what leaving the field blank something that isn't active during the tour. Don't say:
does. Now post the invoice. Instead, explain what to be
aware of when posting.
Avoid stating the obvious and avoid action language
that tells users to do something that isn't active
during the tour. For example, don't say Enter the
customer name here. Instead, explain what to be
aware of when adding a customer.

Teaching tips for FactBoxes


INTRODUCED IN: Business Central 2021 release wave 2

You can add teaching tips for FactBoxes just like pages by using the AboutTitle and AboutText properties is AL.
Adding teaching tips to FactBoxes
Teaching tips are supported on all page types that are supported in FactBoxes, including pages that display cues.
Specifically, you can add teaching tips to following elements:
On the part control that contains the page or cue.
The page or cue that is included in the part control.
Controls, like fields, on the page or cue.
When adding teaching tips, consider the following limitations:
You can't add teaching tips to actions or control add-ins in FactBoxes.
For FactBox teaching tips to activate, the hosting page must have a page teaching tip. The page doesn't need
any control teaching tips.
How FactBox teaching tips fit into tours
The teaching tips for FactBoxes become part of the tour on the hosting page. For more information, see Teaching
tips flow.

Teaching tips flow


When designing teaching tips for a tour, it's important to understand the order in which teaching tips appear.
The flow is as follows:
1. Content area of the main page
a. Page teaching tip
b. Control teaching tips
2. Action bar of the main page
3. FactBoxes
a. Part control teaching tip
b. Page teaching tip
c. Control teaching tips
4. System teaching tips. These teaching tips are for standard features that added are added by the platform and
aren't controlled by AL.

Rich text guidelines for teaching tips


APPLIES TO: Business Central 2022 release wave 1 and later

2022 release wave 1 adds support for rich text formatting for teaching tips. In this section, we take a look at the
rules and guidelines to follow when using rich text in teaching tips, such as bold, italic, or links.
Bold
Bolded text can call out the most important points, such as
Page names, such as Customer Card
Key features, such as Search
Field names, such as Customer
Keyboard shortcuts, such as Alt+Q
Best practices for use of bolded text
Use bolded text sparsely to avoid "shouting".
If a page name or key feature is title cased, it might be a candidate. However, consider if using bold is
needed to help understanding the message.
Consider the difference between a page name such as the **Posted Sales Invoices** list (bolded and
capitalized page name) as opposed to what the list contains such as the list of posted invoices (not
capitalized and not bolded).
If the feature is already mentioned in the title, consider if it's necessary to highlight the word again in the
body text. Bolding a word once in a tip is usually enough.

Italics
Italic text can be used to bring attention to key terms or field values, such as the following:
Key term, such as general ledger
Field value, such as Closed

Links to open pages


Adding links to page teaching tips can be relevant in the following cases:
Links can be added to page teaching tips, to help users discover a key related page in Business Central, such
as linking to the Item Templates page from a teaching tip on the Items list page.
Best practices for use of links
Use links sparsely and use only in page teaching tips. It may be confusing to send users elsewhere.
Don't use links in tour teaching tips, as it will disrupt the tour experience.
The following illustration shows a page teaching tip with a link to guide users to a related page in Business
Central, such as the Posted Sales Invoices list, that users might be looking for in the Sales Invoices list.
Common pitfalls
When you want to call out page names with bold, make sure only the caption is marked, such as
**Sales Invoice** page or **Sales Invoices** list . In these examples, "page" and "list" don't have and
shouldn't have rich text applied.
Don't apply multiple rich text styles to the same word. Apply one type of formatting only, bold, italic, or a
link.

Tooltips and control teaching tips are complementary


There are different rules for tooltips and teaching tips.

TO O LT IP P O IN T IN G AT A F IEL D C A P T IO N T EA C H IN G T IP P O IN T IN G TO A F IEL D

Guidance for tooltips: Guidance for control teaching tips:

Every field and action has a tooltip. Only the most important fields/actions have a
teaching tip.
Answers the question What is this?
Answers the question What can I do with this field or
Relevant for everything since every field/action has a action?
definition.
Isn't relevant for every field/action.

Teaching tips guides users to fields/actions to be


discovered and focus on.

For more information about tooltips, see Help users get unblocked.

Best practices for teaching tips and tours


Not all pages in Business Central need teaching tips and tours. Use teaching tips where they provide
value.
A teaching tip says what can be done (outcome), not how to do it (steps)
A teaching tip is short, and easily read. Usually just two or three short sentences.
Do
Use easy to understand titles that are relevant to the element being pointed to.
Be concise with the information you provide in a teaching tip. Short sentences or sentence fragments are
best.
Keep the tour as short as possible with 1-4 steps.
Titles with a question are OK to use, but use them sparingly.
Use positive cases, don't tell what you can't do.
Follow Microsoft voice guidelines
Don't
Don't provide how-to (steps) or instructional guidance in teaching tips. That content lives on
learn.microsoft.com or in your own documentation.
Don't use large, unformatted blocks of text in a teaching tip.
Don't put obvious tip text, or text that simply repeats what is already on the screen.
If you can't find anything to say, maybe reevaluate if this teaching tip is needed.

See also
Get Users Started with the Checklist
Guidelines for tooltip text
Onboarding experiences in Business Central
AboutTitle Property
AboutText Property
Designing Card and Document Pages
2/6/2023 • 7 minutes to read • Edit Online

The card page type displays selected fields from an underlying table. The document page type is very similar in
structure to the card page, but in addition to fields, it also includes a part that includes another page, called a
sub-page.
Overview
Structure
Behavior points
Developer tips
Designing for devices

Card pages
You design card pages when you want to enable users to view, create, and modify records (master and reference
data) in a table, such as a customer, vendor, or item.
Document pages
Design document pages when you want to represent a transaction or other important event in the domain of
business. Document pages are the computerized counterpart to paper-based documents, such as quotes,
invoices, orders, and so on. As such, document pages often have associated workflow or audit trail
requirements.
Associate with a list page
Both page types are typically associated with list pages (like the customers or sales orders list) that uses the
same table as their source. From the list page, users can select a record and open it the card or document page
for viewing and editing.
Customizing a card and document pages from the client
In the client, users can personalize card pages by rearranging or hiding content as they like. For more
information, see Personalizing Your Workspace.
As a developer or administrator, you can use Designer to customize a card and document page the same way
that individual users personalize their own work spaces. The difference is that changes you make are applied to
all users. For more information, see Using Designer.
Simple Card Page Code Example
2/6/2023 • 2 minutes to read • Edit Online

The AL code in this article creates a simple card page that displays records from an existing table.

For a more detailed explanation of the list page, see Designing Card and Document Pages.

page 50112 SampleCustomerCard


{
PageType = Card;
ApplicationArea = All;
UsageCategory = Administration;
SourceTable = Customer;

//Defines the names for promoted categories for actions.


PromotedActionCategories = 'New,Process,Report,Manage,New Document,Request Approval,Customer';

layout
{
area(Content)
{
//Defines a FastTab that has the heading 'General'.
group(General)
{
field("No."; "No.")
{
ApplicationArea = All;

}
field(Customer; Name)
{
ApplicationArea = All;

}
}

//Defines a FastTab that has the heading 'Contact'.


group(Contact)
{
field(Name; Contact)
{
ApplicationArea = All;

}
field(Phone; "Phone No.")
{
ApplicationArea = All;
}
}
}
}

actions
{
area(Processing)
{

//Defines action that display under the 'Actions' menu.


action("New Sales Quote")
{
ApplicationArea = All;
RunObject = page "Sales Quote";
Promoted = true;
PromotedCategory = New;
Image = NewSalesQuote;
trigger OnAction();
begin

end;
}
action("Banks Account")
{
ApplicationArea = All;
RunObject = page "Customer Bank Account List";
Promoted = true;

//Promotes the action to the category named 'Customer'.


PromotedCategory = Category7;
Image = BankAccount;
trigger OnAction();
begin

end;
}

}
area(Reporting)
{

//Defines action that display under the 'Report' menu.


action("Statement")
{
ApplicationArea = All;
RunObject = codeunit "Customer Layout - Statement";
trigger OnAction();
begin

end;
}
}
}
var
myInt: Integer;
}

See Also
AL Development Environment
Page Extension Object
Actions Overview
Adding Pages and Reports to Search
Personalizing Your Workspace
Using Designer
Teaching tips and in-app tours for onboarding users
2/6/2023 • 9 minutes to read • Edit Online

A key element in educating users about Business Central pages and concepts is the tour. A tour is a sequence of
teaching tips.
Teaching tips can be defined at the page level, the page teaching tip, and be followed by teaching tips at the
control level, the control teaching tips. Both types of teaching tips are defined by the .AL properties AboutTitle
and AboutText , and an extension can overwrite teaching tips in the default version.

Page teaching tips


The primary purpose is to increase the user's chance of success with the page. So, the title and
description of the page teaching tip should answer the following hypothetical user questions:
AboutTitle : What is this page about?
AboutText : What can I do with this page?
Teaching tips explain Business Central logic that is relevant to the page.
Teaching tips let users discover and initiate the related tour whenever they are ready for it.
Allow users to get on with a task right away without blocking them.
A teaching tip can be defined for any page in Business Central, except the role centers, dialogs, and
request pages for reports.
After users dismiss a teaching tip and tour, they can choose or hover over the page title. This action will
reopen the teaching tip, and the user can retake the tour, for example.
On a page that is opened from the checklist, the tour is considered an invited tour, and the page teaching
tip has a Go back button that takes the user back to the checklist.
The following illustration shows a page teaching tip that explains what the page is about and can invite the user
to take a tour. The teaching tip renders in the lower left corner.

The following illustration shows how choosing the page title will reopen the teaching tip so that the user can
retake the tour.
How to write page teaching tips
There are different rules for teaching tips for lists versus cards and documents.

L IST PA GE W IT H T EA C H IN G T IP C A RD PA GE W IT H T EA C H IN G T IP

AboutTitle : About sales invoices AboutTitle : About sales invoice details


AboutText : Sales invoices appear in this list until they're AboutText : You can update and add to the sales invoice
finalized and posted. After an invoice is posted, find it again until you post it. If you leave the invoice without posting,
in the Posted Sales Invoices list. you can return to it later from the list of ongoing invoices.

Answers the following questions: Answers the following questions:

What can I do on this page in general? What can I do on this page with this particular field
or action?
Is there a related entity I should know about?
What is the desired outcome of the task in this page?
The title for a list page teaching tip will typically use
the plural form, such as About sales invoices The title for a card or document page teaching tip will
typically be [entity name] + details, such as About
sales invoice details

What you should know about tours


Tours are sequential teaching tips describing functionality while pointing to elements in the UI.
The tour guides the user around the page.
Tours can be initiated from the page teaching tip
During a tour, a page with input fields will be in read mode.
Tours show where to find something, what it is, what it means, what you can do with it, and what it
affects.
A control teaching tip can point out a value that the user must check to know their next step.
Example: The Status field on an invoice. When the status is open, the user can edit the invoice.
A control teaching tip can describe the relevant timing for when to use a field or action.
Example: The Post action: When done editing, then post and send.

How to write teaching tips for controls


There are different rules for teaching tips for input fields and actions.

T EA C H IN G T IP P O IN T IN G TO A N IN P UT F IEL D T EA C H IN G T IP P O IN T IN G TO A N A C T IO N

AboutTitle: Who you are selling to Content example for the Post action:
AboutText: This can be an existing customer, or you can AboutTitle: When all is set, you post
register a new from here. Customers can have special prices AboutText: After entering the sales lines and other
and discounts that are automatically used when you enter information, you post the invoice to make it count. After
the sales lines. posting, the sales invoice is moved to the Posted Sales
Invoices list.

The teaching tip can point to a field that may or may With multiple similar actions,such as Post and Post
not have data. & New , call out the simplest version only.

A control teaching tip can explain an important Avoid action language that tells users to do
value's meaning, such as what leaving the field blank something that isn't active during the tour. Don't say:
does. Now post the invoice. Instead, explain what to be
aware of when posting.
Avoid stating the obvious and avoid action language
that tells users to do something that isn't active
during the tour. For example, don't say Enter the
customer name here. Instead, explain what to be
aware of when adding a customer.

Teaching tips for FactBoxes


INTRODUCED IN: Business Central 2021 release wave 2

You can add teaching tips for FactBoxes just like pages by using the AboutTitle and AboutText properties is AL.
Adding teaching tips to FactBoxes
Teaching tips are supported on all page types that are supported in FactBoxes, including pages that display cues.
Specifically, you can add teaching tips to following elements:
On the part control that contains the page or cue.
The page or cue that is included in the part control.
Controls, like fields, on the page or cue.
When adding teaching tips, consider the following limitations:
You can't add teaching tips to actions or control add-ins in FactBoxes.
For FactBox teaching tips to activate, the hosting page must have a page teaching tip. The page doesn't need
any control teaching tips.
How FactBox teaching tips fit into tours
The teaching tips for FactBoxes become part of the tour on the hosting page. For more information, see Teaching
tips flow.

Teaching tips flow


When designing teaching tips for a tour, it's important to understand the order in which teaching tips appear.
The flow is as follows:
1. Content area of the main page
a. Page teaching tip
b. Control teaching tips
2. Action bar of the main page
3. FactBoxes
a. Part control teaching tip
b. Page teaching tip
c. Control teaching tips
4. System teaching tips. These teaching tips are for standard features that added are added by the platform and
aren't controlled by AL.

Rich text guidelines for teaching tips


APPLIES TO: Business Central 2022 release wave 1 and later

2022 release wave 1 adds support for rich text formatting for teaching tips. In this section, we take a look at the
rules and guidelines to follow when using rich text in teaching tips, such as bold, italic, or links.
Bold
Bolded text can call out the most important points, such as
Page names, such as Customer Card
Key features, such as Search
Field names, such as Customer
Keyboard shortcuts, such as Alt+Q
Best practices for use of bolded text
Use bolded text sparsely to avoid "shouting".
If a page name or key feature is title cased, it might be a candidate. However, consider if using bold is
needed to help understanding the message.
Consider the difference between a page name such as the **Posted Sales Invoices** list (bolded and
capitalized page name) as opposed to what the list contains such as the list of posted invoices (not
capitalized and not bolded).
If the feature is already mentioned in the title, consider if it's necessary to highlight the word again in the
body text. Bolding a word once in a tip is usually enough.

Italics
Italic text can be used to bring attention to key terms or field values, such as the following:
Key term, such as general ledger
Field value, such as Closed

Links to open pages


Adding links to page teaching tips can be relevant in the following cases:
Links can be added to page teaching tips, to help users discover a key related page in Business Central, such
as linking to the Item Templates page from a teaching tip on the Items list page.
Best practices for use of links
Use links sparsely and use only in page teaching tips. It may be confusing to send users elsewhere.
Don't use links in tour teaching tips, as it will disrupt the tour experience.
The following illustration shows a page teaching tip with a link to guide users to a related page in Business
Central, such as the Posted Sales Invoices list, that users might be looking for in the Sales Invoices list.
Common pitfalls
When you want to call out page names with bold, make sure only the caption is marked, such as
**Sales Invoice** page or **Sales Invoices** list . In these examples, "page" and "list" don't have and
shouldn't have rich text applied.
Don't apply multiple rich text styles to the same word. Apply one type of formatting only, bold, italic, or a
link.

Tooltips and control teaching tips are complementary


There are different rules for tooltips and teaching tips.

TO O LT IP P O IN T IN G AT A F IEL D C A P T IO N T EA C H IN G T IP P O IN T IN G TO A F IEL D

Guidance for tooltips: Guidance for control teaching tips:

Every field and action has a tooltip. Only the most important fields/actions have a
teaching tip.
Answers the question What is this?
Answers the question What can I do with this field or
Relevant for everything since every field/action has a action?
definition.
Isn't relevant for every field/action.

Teaching tips guides users to fields/actions to be


discovered and focus on.

For more information about tooltips, see Help users get unblocked.

Best practices for teaching tips and tours


Not all pages in Business Central need teaching tips and tours. Use teaching tips where they provide
value.
A teaching tip says what can be done (outcome), not how to do it (steps)
A teaching tip is short, and easily read. Usually just two or three short sentences.
Do
Use easy to understand titles that are relevant to the element being pointed to.
Be concise with the information you provide in a teaching tip. Short sentences or sentence fragments are
best.
Keep the tour as short as possible with 1-4 steps.
Titles with a question are OK to use, but use them sparingly.
Use positive cases, don't tell what you can't do.
Follow Microsoft voice guidelines
Don't
Don't provide how-to (steps) or instructional guidance in teaching tips. That content lives on
learn.microsoft.com or in your own documentation.
Don't use large, unformatted blocks of text in a teaching tip.
Don't put obvious tip text, or text that simply repeats what is already on the screen.
If you can't find anything to say, maybe reevaluate if this teaching tip is needed.

See also
Get Users Started with the Checklist
Guidelines for tooltip text
Onboarding experiences in Business Central
AboutTitle Property
AboutText Property
Designing Assisted Setup Guides
2/6/2023 • 11 minutes to read • Edit Online

In Business Central, you use the NavigatePage page type to create an assisted setup. An assisted setup, also
called a wizard, is a page that consists of one or more user input pages or steps. These steps are linked together,
enabling users to carry out infrequently performed tasks, such as configuration or specific business tasks. In the
client, the NavigatePage page doesn't an action bar. It's designed to have buttons at the bottom that let users
move back and forth through the steps by selecting the Back and Next buttons, until they finish by selecting the
Finish button.

An example in Business Central is the Company Setup assisted setup, page 1803.

Build the assisted setup


This section describes the basic tasks for creating an assisted setup. It gives you an understanding of the general
structure of an assisted setup guide. Knowing this information will help you build assisted setup guides that look
and feel like the ones provided by Microsoft. This section includes some basic AL code for the various steps
involved in creating an assisted setup guide. For more information about the code and logic, see the full
example in this article. The example code for reference only, and your implementation may vary.
1. Create a page for the assisted setup, for example:
page 50100 ToDoAssistedSetup
{
PageType = NavigatePage;
SourceTable = "To-do";
SourceTableTemporary = true;
Caption = 'Add a To-Do for the Team';
}

Set the following properties:

P RO P ERT Y DESC RIP T IO N A N D VA L UE

PageType property Set to NavigatePage .

SourceTable Set to the name of the table that stores the data for the
assisted setup.

SourceTableTemporary Set to true . The reason is because Business Central


automatically stores all modifications to database tables
as soon as users move focus to another field or close the
page. Using a temporary table let's users exit the
assisted setup guide at any point, without saving the
changes they've made so far to the database. Instead,
the data modifications are only stored in memory, until
code is run to transfer the data to the database.

Caption Set to the title that you want to show on the top of each
step of the assisted guide.

2. Add the steps that comprise the assisted setup.


For each step that you want in the guide, add a group() control to the root-level of the layout >
area(Content) control. For example, the following code adds three steps.
layout
{
area(Content)
{
group(Step1)
{
Caption = '';
InstructionalText = '';
Visibility = Step1Visible;

}
group(Step2)
{
Caption = '';
InstructionalText = '';
Visibility = Step2Visible;

field(Field2; "Field2")
{
ApplicationArea = All;
Caption = '';
}
}
group(Step3)
{
Caption = '';
InstructionalText = '';
Visibility = Step3Visible;
}
}
}

var
Step1Visible: Boolean;
Step2Visible: Boolean;
Step3Visible: Boolean;
Step: Option Start,Fill,Finish;

local procedure EnableControls()


begin
ResetControls();
case Step of
Step::Start:
ShowStep1();
Step::Fill:
ShowStep2();
Step::Finish:
ShowStep3();
end;
end;

The individual group() controls define the content to display for the step, like text and data entry
fields. For example, use the Caption and InstructionalText properties to add text. Use field() controls
for source table fields.
The order of the group() controls doesn't necessarily determine the order of the steps in the assisted
setup. You'll add AL code to define the logic for when each step appears.
You can include group() controls within the root-level group() controls. These subgroups can be
useful for adjusting the layout fields on a step and adding captions and instructional text.
Because only one step can be shown at a time, you have to add logic to control when each step is shown.
To control the visibility, add the following code:
For each step, define a global boolean variable or a step number condition and apply it the group's
Visible property. The example, uses the boolean variables Step1Visible , Step2Visible , and
Step2Visible .
You'll then have to add AL code to change these variables depending on which step the user is
working on.
Define a global option variable that has a value for each step.
You'll use this variable in code to track which step is active.

NOTE
Multiline fields shown inside a step are shown without a gray background. This behavior allows you to write a list
of items or any formatted text that requires new lines.

3. Add the navigation buttons.


Assisted setups typically have a Back , Next , and Finish button at the bottom-right of the page. Add each
button by using an action() control.
actions
{
area(Processing)
{
action(Back)
{
Enabled = BackEnable;
InFooterBar = true;
Image = PreviousRecord;

trigger OnAction()
begin
NextStep(true);
end;
}
action(Next)
{
Enabled = NextEnable;
InFooterBar = true;
Image = NextRecord;

trigger OnAction()
begin
NextStep(false);
end;
}
action(Finish)
{
Enabled = FinishEnable;
InFooterBar = true;
Image = Approve;

trigger OnAction()
begin
Finished();
end;
}
}
}

var
BackEnable: Boolean;
NextEnable: Boolean;
FinishEnable: Boolean;

local procedure NextStep(Backwards: Boolean)


begin
if Backwards then
Step := Step - 1
else
Step := Step + 1;
EnableControls();
end;

local procedure Finished()


begin
StoreRecordVar();
CurrPage.Close();
end;

Set the InFooterBar property for each to true .


If the property isn't set or is false , then the actions won't' appear.
Similar to the Visible property on the groups, use the Enabled property to control when buttons
are active on the different steps. For example, Back isn't active in the first step, and Next isn't
active in the last step.
Like on groups, define global boolean variables for each action, then apply the variable to the
action's Editable property. The global variables are then controlled in AL code.
To style the buttons to match other assisted setups in the Microsoft base application, set the Image
property to PreviousRecord for the back button, NextRecord for the next button, and Approve for
the finish.
4. Transfer data from the temporary table to the database table. For example:

var
ToDoRec: Record "To-do";

local procedure StoreRecordVar();


begin
ToDoRec.TransferFields(Rec, true);
ToDoRec.Insert();
end;

In this example, the StoreRecordVar procedure is called from the Finished procedure used on the
actions.

Add standard banners


You may have noticed that most assisted setup guides in the base application, and in this article, include two
different banners under the step caption: a gear and a check mark. These banners are based on the following
image files in Media Repositor y table:
AssistedSetup-NoText-400px.png for the gear
AssistedSetupDone-NoText-400px.png for the check mark.
You can reuse these images in your custom assisted setup guides to provide a consistent look.
To a display the banners, add two root-level group() controls in to the area(Content) control, like for the steps.
Use field() controls for displaying the gear and check mark images. The following snippets illustrate one way
of adding the banners:
...
layout
{
area(Content)
{
...
group(StandardBanner)
{
Caption = '';
Editable = false;
Visible = TopBannerVisible and not FinishActionEnabled;
field(MediaResourcesStandard; MediaResourcesStandard."Media Reference")
{
ApplicationArea = All;
Editable = false;
ShowCaption = false;
}
}
group(FinishedBanner)
{
Caption = '';
Editable = false;
Visible = TopBannerVisible and FinishActionEnabled;
field(MediaResourcesDone; MediaResourcesDone."Media Reference")
{
ApplicationArea = All;
Editable = false;
ShowCaption = false;
}
}
}
}
...
var
...
MediaRepositoryDone: Record "Media Repository";
MediaRepositoryStandard: Record "Media Repository";
MediaResourcesDone: Record "Media Resources";
MediaResourcesStandard: Record "Media Resources";

trigger OnInit();
begin
...
LoadTopBanners();
end;

local procedure LoadTopBanners();


begin
if MediaRepositoryStandard.Get('AssistedSetup-NoText-400px.png', Format(CurrentClientType())) and
MediaRepositoryDone.Get('AssistedSetupDone-NoText-400px.png', Format(CurrentClientType()))
then
if MediaResourcesStandard.Get(MediaRepositoryStandard."Media Resources Ref") and
MediaResourcesDone.Get(MediaRepositoryDone."Media Resources Ref")
then
TopBannerVisible := MediaResourcesDone."Media Reference".HasValue();
end;

Add to the Assisted Setup page


Page 1901 "Assisted Setup" of the base application gives users quick access to all assisted setup guides. This
section explains how you can add your assisted setup guide to the page.
The base application includes several objects that control what items appear in the Assisted Setup page. For
example, table 1990 "Guided Experience Item" is an internal table that's the source for the Assisted Setup
page. Codeunit 1990 "Guided Experience" is used to register your assisted setup guide in the Guided
Experience Item table and run it from the Assisted Setup page. The Guided Experience codeunit publishes
the OnRegisterAssistedSetup event that notifies the Assisted Setup page to add new items.

[IntegrationEvent(false, false)]
internal procedure OnRegisterAssistedSetup()
begin
end;

To add an assisted setup guide to the Assisted Setup page, add a codeunit that subscribes to the
OnRegisterAssistedSetup event. The following code illustrates how you can add the ToDoAssistedSetup
assisted setup guide. The example also creates a new category called Tasks on the Assisted Setup page a link
to ToDoAssistedSetup will be listed:

codeunit 50100 "AddToDoAssistedSetup"


{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Guided Experience", 'OnRegisterAssistedSetup', '',
true, true)]
local procedure OnRegisterAssistedSetup()
var
AssistedSetup: Codeunit "Guided Experience";
GuidedExperienceType: Enum "Guided Experience Type";
AssistedSetupGroup: Enum "Assisted Setup Group";
VideoCategory: Enum "Video Category";
begin
if not AssistedSetup.Exists(GuidedExperienceType::"Assisted Setup",
ObjectType::Page,
Page::"ToDoAssistedSetup") then
AssistedSetup.InsertAssistedSetup(
// Link text for the assisted setup guide
'Add a to-do',
// Short description, not shown on page
'Create a task for your team',
// Text that shows in Description column
'Register a task for your team and assign people',
1,
ObjectType::Page,
Page::ToDoAssistedSetup,
// Assign guide to Task category
AssistedSetupGroup::Tasks,
//Video URL not required
'',
VideoCategory::Uncategorized,
//Help URL not required
'');
end;
}

enumextension 50100 MyEnumExtension extends "Assisted Setup Group"


{
value(100; Tasks)
{
}
}

Example
This code example shows how to use a NavigatePage type page to create an assisted setup guide with three
steps, as illustrated in the following figures. The assisted setup lets users add entries to a to-do list, which is
stored in table To-Do . The code for the first step includes a part that reuses the page Attendee Wizard
Subform of the base application. This part allows users, when they first start the setup, to select the salesperson
that the to-do is for.

ST EP 1 ST EP 2 ST EP 3

Code

page 50111 ToDoAssistedSetup


{
PageType = NavigatePage;
SourceTable = "To-do";
SourceTableTemporary = true;
Caption = 'Add a To-Do for the Team';

layout
{
area(Content)
{
group(Step1)
{
Visible = Step1Visible;

group("Welcome")
{
Caption = 'Welcome to the to-do assisted setup';
group(group11)
{
Caption = '';
InstructionalText = 'Use this guide to register a to-do task for you and your
team.';
}
}
group("Let's go")
{
Caption = 'Let''s go';
group(group12)
{
Caption = '';
InstructionalText = 'Select Next to get started.';
}
}
}
group(Step2)
{
Caption = 'Enter information about the to-do task';
Visible = Step2Visible;

group("11")
{
Caption = 'Add attendees and fill in details';
part(AttendeeSubForm; "Attendee Wizard Subform")
{
}
}
}
field("No."; Rec."No.")
{
ApplicationArea = All;
Visible = false;
}
field("Type"; Rec."Type")
{
ApplicationArea = All;
Caption = 'What type is the to-do?';

}
field("Date"; Rec."Date")
{
ApplicationArea = All;
Caption = 'What''s the start date?';

}
field("Description"; Rec.Description)
{
ApplicationArea = All;
Caption = 'Describe your to-do';
}
field("Start Time"; Rec."Start Time")
{
ApplicationArea = All;
Caption = 'What''s the start time?';
}
field("Duration"; Rec."Duration")
{
ApplicationArea = All;
Caption = 'How long does it last?';

}
field("Team To-do"; Rec."Team to-do")
{
ApplicationArea = All;
Caption = 'Team to-do';

}
field("All Day Event"; Rec."All Day Event")
{
ApplicationArea = All;
Caption = 'All Day Event';

}
field("Ending Date"; Rec."Ending Date")
{
ApplicationArea = All;
Caption = 'What''s the end date?';
}
field("Ending Time"; Rec."Ending Time")
{
ApplicationArea = All;
Caption = 'What''s the end time?';
}
// }
}
group(Step3)
{
Caption = 'That''s it!';
InstructionalText = 'Select Finish to save the to-do.';
Visible = Step3Visible;

}
group(StandardBanner)
{
Caption = '';
Editable = false;
Visible = TopBannerVisible and not FinishActionEnabled;
field(MediaResourcesStandard; MediaResourcesStandard."Media Reference")
{
ApplicationArea = All;
Editable = false;
ShowCaption = false;
}
}
group(FinishedBanner)
{
Caption = '';
Editable = false;
Visible = TopBannerVisible and FinishActionEnabled;
field(MediaResourcesDone; MediaResourcesDone."Media Reference")
{
ApplicationArea = All;
Editable = false;
ShowCaption = false;
}
}
}
}

actions
{
area(Processing)
{
action(Back)
{
ApplicationArea = All;
Caption = '&Back';
Enabled = BackEnable;
InFooterBar = true;
Image = PreviousRecord;

trigger OnAction()
begin
NextStep(true);
end;
}
action(Next)
{
ApplicationArea = All;
Caption = '&Next';
Enabled = NextEnable;
InFooterBar = true;
Image = NextRecord;

trigger OnAction()
begin
NextStep(false);
end;
}
action(Finish)
{
ApplicationArea = All;
Caption = '&Finish';
Enabled = FinishEnable;
InFooterBar = true;
Image = Approve;

trigger OnAction()
begin
Finished();
end;
}
}
}
trigger OnInit()
var

begin

EnableControls();
LoadTopBanners();
end;

trigger OnOpenPage()
begin
ToDoRec.Get();
ToDoRec.Init;
Rec := ToDoRec;
CurrPage.Update();
end;

var
BackEnable: Boolean;
NextEnable: Boolean;
FinishEnable: Boolean;
Step1Visible: Boolean;
Step2Visible: Boolean;
Step3Visible: Boolean;
Step: Option Start,Fill,Finish;
ToDoRec: Record "To-do";
TopBannerVisible: Boolean;
FinishActionEnabled: Boolean;
MediaRepositoryDone: Record "Media Repository";
MediaRepositoryStandard: Record "Media Repository";
MediaResourcesDone: Record "Media Resources";
MediaResourcesStandard: Record "Media Resources";

local procedure NextStep(Backwards: Boolean)


begin
if Backwards then
Step := Step - 1
else
Step := Step + 1;

EnableControls();
end;

local procedure Finished()


begin
StoreRecordVar();
CurrPage.Close();
end;

local procedure EnableControls()


begin
ResetControls();
case Step of
Step::Start:
ShowStep1();
Step::Fill:
ShowStep2();
Step::Finish:
ShowStep3();
end;
end;

local procedure ShowStep1()


begin
Step1Visible := true;
BackEnable := false;
NextEnable := true;
FinishEnable := false;
FinishEnable := false;
end;

local procedure ShowStep2()


begin
Step2Visible := true;
BackEnable := true;
NextEnable := true;
FinishEnable := false;
end;

local procedure ShowStep3()


begin
Step3Visible := true;
BackEnable := true;
NextEnable := false;
FinishEnable := true;
FinishActionEnabled := true
end;

local procedure ResetControls();


begin
FinishEnable := false;
BackEnable := true;
NextEnable := true;
Step1Visible := false;
Step2Visible := false;
Step3Visible := false;

end;

local procedure StoreRecordVar();


begin
ToDoRec.TransferFields(Rec, true);
ToDoRec.Insert();
end;

local procedure LoadTopBanners();


begin
if MediaRepositoryStandard.Get('AssistedSetup-NoText-400px.png', Format(CurrentClientType())) and
MediaRepositoryDone.Get('AssistedSetupDone-NoText-400px.png', Format(CurrentClientType()))
then
if MediaResourcesStandard.Get(MediaRepositoryStandard."Media Resources Ref") and
MediaResourcesDone.Get(MediaRepositoryDone."Media Resources Ref")
then
TopBannerVisible := MediaResourcesDone."Media Reference".HasValue();

end;
}
codeunit 50100 "AddToDoAssistedSetup"
{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Guided Experience", 'OnRegisterAssistedSetup', '',
true, true)]
local procedure OnRegisterAssistedSetup()
var
AssistedSetup: Codeunit "Guided Experience";
GuidedExperienceType: Enum "Guided Experience Type";
AssistedSetupGroup: Enum "Assisted Setup Group";
VideoCategory: Enum "Video Category";
begin
if not AssistedSetup.Exists(GuidedExperienceType::"Assisted Setup",
ObjectType::Page,
Page::"ToDoAssistedSetup") then
AssistedSetup.InsertAssistedSetup(
'Add a to-do',
'Create a task for your team',
'Register a task for your team and assign people',
1,
ObjectType::Page,
Page::ToDoAssistedSetup,
Page::ToDoAssistedSetup,
AssistedSetupGroup::Tasks,
'',
VideoCategory::Uncategorized,
'');
end;
}

enumextension 50100 MyEnumExtension extends "Assisted Setup Group"


{
value(100; Tasks)
{
}
}

See Also
Page Parts Overview
2/6/2023 • 5 minutes to read • Edit Online

Parts are a special category of page designed to be embedded within another page. The hosting page can be
composed of one or more page parts. Parts are useful when designing richer user experiences, by displaying
information from a table that is different from the source table of the hosting page. Using parts is a great way to
reuse your code across multiple pages.

Hosting parts on a page


The following table illustrates how parts could be creatively arranged on a page to deliver unique experiences.

IL L UST RAT IO N O F PA GE PAT T ERN EXP L A N AT IO N

Pages of type Role Center are typically composed of


multiple pages parts. These parts typically display business
headlines, KPIs, and other cues to help users get an
overview of their work.

Most page types can display a number of FactBoxes in the


FactBox pane, that display information related to the current
record.
IL L UST RAT IO N O F PA GE PAT T ERN EXP L A N AT IO N

Pages of type Document are used to model transactional


data that typically consists of a header and detailed lines.
Since these records come from different tables, a part is used
to display lines that originate from a related table.

Related lists can be displayed above each other. This pattern


is a common pattern allowing one list to be filled by the
selected record of another list. Note: We're working on
adding guidance for more optimal layouts.
IL L UST RAT IO N O F PA GE PAT T ERN EXP L A N AT IO N

When records from two tables need to be compared


together, parts can be displayed side by side. Note: We're
working on adding guidance for more optimal layouts.

Different types of parts


Business Central offers different types of parts that display data in a specific way.

PA GET Y P E P URP O SE H O ST IN G PA GE T Y P ES

ListPar ts Display a list of records. Role Centers; FactBoxes on pages of


type Card, Document, Worksheet, List,
ListPlus; Tabular step in a Wizard;
Subpage on a Document page.

CardPar ts Flexible canvas that can be used to Role Centers; FactBoxes on pages of
display almost any page controls, such type Card, Document, Worksheet, List,
as fields, cue tiles, charts, images, or ListPlus; Step in a Wizard.
control add-ins.

Power BI Repor t Par ts Used for displaying Power BI reports. Role Centers; Fact boxes; Card pages

HeadlinePar ts Display relevant insights from across Role Centers only.


the business.

Adding a part to a page


To add a part to a page in Visual Studio Code, you add a part control on the hosting page object that references
the page part object. The part control also defines a small set of properties, such as the caption that will
accompany the part. This allows separation of responsibility: the page part object defines self-contained
functionality, whilst the hosting page defines how the container of the part should behave without knowledge of
its' functionality.
For more information about the properties of a part control, see Page Properties.

Design considerations
Part size
The size of a part is automatically determined by the user interface and will vary depending on where the part
has been embedded on the page, other content surrounding the part, and the overall available space of the
display target. Developers can't specify the preferred, minimum, or maximum height or width of a part.
Part actions
A part can define actions that operate on the fields within the part or navigate to another page. The area in
which a part is embedded on a page determines how the action menu is displayed.
In the FactBoxes or RoleCenter area of the hosting page, parts display a condensed action menu.
In the Content area of the hosting page, parts will only display an expanded action menu if they satisfy the
following rules:
parts are hosted on a card or document page.
parts aren't placed within a FastTab.
Collapsed or expanded parts
The area in which a part is embedded on a page determines whether the part can be collapsed.
In the FactBoxes or RoleCenter area of the hosting page, parts can't be collapsed.
In the Content area of the hosting page, parts can only be collapsed if they satisfy the following rules:
parts are hosted on a task dialog, card, or document page.
parts aren't placed within a FastTab.
Dynamics 365 Business Central automatically determines whether parts are initially displayed as expanded or
collapsed. For example, when a document page is opened the first time, the first two parts or FastTabs are
automatically expanded and all other parts and FastTabs are shown as collapsed to provide an optimal starting
experience. Users can change the state of a part to be expanded or collapsed directly within the user interface,
but developers can't specify the starting state.
Choosing the visibility of parts
Parts can be hidden on the hosting page to provide an optimal starting experience. For example, a part could be
hidden because it contains secondary content, or content that is needed by only some categories of users. To
hide a part, set the Visible property of the part to false on the hosting page.
When you design a page with hidden parts, users can choose to display those parts again using personalization
and role customization features in the user interface. Parts can be made visible programmatically using an
expression, for example, depending on whether the feature has been set up by administrators. Learn more about
Dynamic Visibility of Controls.

NOTE
Parts embedded on Role Center pages can't be made visible using expressions, because the hosting Role Center page can't
execute code.

Using page background tasks


Like other page types, you can design a part page to use one or more page background tasks. However, unlike
other page types, a part page won't display any data until all page background tasks have completed. For more
information about this behavior, see Designing part pages for page background tasks.
Good to know
Parts can either represent self-contained functionality, or can be contextual and exchange information with
the hosting page.
A part can't be hosted within another part. Business Central allows a maximum of one level of page nesting.
Parts can't be placed within repeater controls.
Parts aren't intended to be displayed on their own without a hosting page.

See Also
AL Development Environment
Page Types and Layouts
FactBoxes
Headlines
List Parts
Card Parts
Power BI Report Parts Page Extension Object
Personalizing Your Workspace
Using Designer
Working with List Parts
2/6/2023 • 2 minutes to read • Edit Online

A ListPart page is a type of page part used to display a list of records embedded within another page. It consists
of a repeater, which presents the records of the source table as rows and columns, and optionally, of an action
bar.
A list part can be contained in Role Centers, in the FactBox and content area of other pages, in a tabular step in a
Wizard and as a subpage in a Document page. Depending on the type of the hosting page, a list part is subject
to different design constraints, which determine its position and dimensions. For more information, see Design
Considerations.

Creating a list part


To create a list part, you create a page object, set the PageType Property to ListPart and specify the source
table. A list part page uses a single repeater control, located inside area(Content) , where you specify the
field controls that you want to display. The structure is similar to that of a List page, except that there is no
FactBox section, since part pages cannot host other parts. For more information, see List Page Structure.

Adding a list part to a page


To place the list part in a page, you add a part control to the hosting page and associate it with the list part
page object. Here you can also define additional properties. These will only apply to the container of the list part,
whose functionality is independent from the hosting page.

Example
The following code sample illustrates how to create a ListPart page, "Pending Shipments" , and how to
integrate it in the card page "Customer Card" .
page 50101 "Pending Shipments"
{
PageType = ListPart;
SourceTable = "Sales Header";
// Filter on the sales orders that are pending completion.
SourceTableView = WHERE("Completely Shipped" = CONST(False));

layout
{
area(Content)
{
repeater(General)
{
field("No."; "No.")
{
ApplicationArea = All;
}
field("Order Date"; "Order Date")
{
ApplicationArea = All;
}
field("Location Code"; "Location Code")
{
ApplicationArea = All;
}
}
}
}
}

page 50102 "Customer Card"


{
PageType = Card;
SourceTable = Customer;

layout
{
area(Content)
{
group(General)
{
field("No."; "No.")
{
ApplicationArea = All;
}
field(Name; Name)
{
ApplicationArea = All;
}
}
group(Shipments)
{
part("Pending Shipments"; "Pending Shipments")
{
// Filter on the sales orders that relate to the customer in the card page.
SubPageLink = "Sell-to Customer No." = FIELD("No.");
}
}
}
}
}

See Also
Page Parts Overview
Page Types and Layouts
Designing List Pages
Page Object
Page Extension Object
Adding a FactBox to a page
CardPart Pages
AL Development Environment
Using Designer
Working with Card Parts
2/6/2023 • 2 minutes to read • Edit Online

A CardPart page is a type of page part embedded within another page used to display additional data relevant
to the page that hosts it. It can display the data in the form of almost any page control, such as fields, cue tiles,
charts, images, or control add-ins. You can also define actions to operate on the card part page.
A card part can be placed in Role Centers, in the FactBox and content area of other pages or in a tabular step in a
Wizard. Depending on the type of the hosting page, a card part is subject to different design constraints, which
determine its position and dimensions. For more information, see Design Considerations.

Creating a card part


To create a card part, you create a page object, set the PageType Property to CardPart and specify the source
table. You can nest different controls inside the area(Content) control depending on how you want to display
the data. The controls you can specify are the following.

C O N T RO L DEF IN IT IO N

field Defines a field. It can also be used to display an image.

cuegroup Defines a group of cue tiles. For more information, see


Designing Cues.

chartpart Defines a chart.

usercontrol Defines a control add-in. For more information, see Control


Add-In Object.

Adding a card part to a page


To place a card part in a page, you add a part control to the hosting page and associate it with the card part
page object. Here you can also define additional properties. These will only apply to the container of the card
part, whose functionality is independent from the hosting page.

Example
The following code sample illustrates how to create a CardPart page, "Customer Sales History" , and how to
integrate it in the FactBox area of the card page "Customer Card" .

page 50101 "Customer Sales History"


{
PageType = CardPart;
SourceTable = Customer;

layout
{
area(Content)
{
// Display data as cue tiles
cuegroup(Overview)
{
field("No. of Quotes"; "No. of Quotes")
field("No. of Quotes"; "No. of Quotes")
{
ApplicationArea = All;
// Make the cue interactive
DrillDownPageID = "Sales Quotes";
}
field("No. of Orders"; "No. of Orders")
{
ApplicationArea = All;
DrillDownPageID = "Sales Order List";
}
field("No. of Invoices"; "No. of Invoices")
{
ApplicationArea = All;
DrillDownPageID = "Sales Invoice List";
}
}
}
}
}

page 50102 "Customer Card"


{
PageType = Card;
SourceTable = Customer;

layout
{
area(Content)
{
group(General)
{
field("No."; "No.")
{
ApplicationArea = All;
}
field(Name; Name)
{
ApplicationArea = All;
}

}
}

// Display the card part in the Factbox area


area(FactBoxes)
{
part("Customer Sales History"; "Customer Sales History")
{
// Filter on the sales history that relate to the customer in the card page.
SubPageLink = "No." = FIELD("No.");
}
}
}
}

See Also
Page Parts Overview
Page Types and Layouts
Page Object
Page Extension Object
Adding a FactBox to a page
ListPart Pages
AL Development Environment
Using Designer
Creating a Role Center Headline
2/6/2023 • 5 minutes to read • Edit Online

You can set up a Role Center to display a series of headline texts that appear one by one for a predefined period
of time.

The headlines can provide users with up-to-date information and insight into the business and daily work.
Typical categories of headlines might include:
My performance
My workday
Organizational health
Productivity tips
Cross-tenant insights (performance relative to peers)
Getting started information

IMPORTANT
Headlines will only appear in the Web client; they will not be shown on other client types.

NOTE
Headlines can display numbers and letters only. For example, headlines cannot display images.

Design concept
In development
In short, the Headline is basically a page that contains one or more fields. The page must be the HeadlinePar t
type page. Each field defines an individual headline to be displayed. The source for a field can be an expression
or a field in an underlying table.
The HeadlinePar t page is designed for Role Centers, that is, pages that have the type RoleCenter . If you
use a HeadlinePar t page on another page type, the part will not render in the client.
Using the OnDrillDown trigger, headlines can be made interactive, meaning that users can select the
headline to dig deeper into numbers or values that are shown in the headline or link to another page or
URL.
You can dynamically toggle visibility of a specific headline, for example based on its relevancy, by setting
the Visible property on the field.
There are only a few field properties that apply to fields that are used on a HeadlinePar t type page,
including Expression, Visible, ApplicationArea, Drilldown, and DrillDownPageID. All other properties are
ignored.
In the client
The Role Center will start by displaying the first visible headline that is defined on the HeadlinePart page. The
headline will appear for 5 seconds, then the next headline will appear for 5 seconds, and so on. When all the
headlines have been displayed, it will cycle back to the first headline, and continue from there.
If a headline is interactive, users can select the headline to open the target defined in the headline.
Users can pause on a headline by pointing to it.
Users can manually switch among headlines by selecting a corresponding dot that is displayed under the
headlines.
Users can personalize their Role Center to show or hide the Headline part as they like.

Creating a HeadlinePart page


1. Implement the logic that resolves field expressions for the headlines that you will use on the page.
You can apply more flexible and complex patterns, such as having data tables drive the text, drill-down
and relevance engine for headlines.
2. Create a page that has the PageType property set to HeadlinePart .
3. For each headline, add a field, and set the Expression property. The order of the fields, determines the
order in which they appear.
The following example shows the AL code for a simple HeadlinePar t page that consists of four fields
that display static text.
page 50100 RoleCenterHeadline
{
PageType = HeadLinePart;

layout
{
area(content)
{
field(Headline1; hdl1Txt)
{

}
field(Headline2; hdl2Txt)
{

}
field(Headline3; hdl3Txt)
{

}
field(Headline4; hdl4Txt)
{

}
}
}

var
hdl1Txt: Label 'This is headline 1';
hdl2Txt: Label 'This is headline 2';
hdl3Txt: Label 'This is headline 3';
hdl4Txt: Label 'This is headline 4';
}

4. You can now add the HeadlinePar t page to the RoleCenter page.

Constructing Headlines with the Expression property


The Expression property supports the following syntax that enables you to specify a title for the headline, the
headline text itself, and emphasize a string of text in the headline:

'<qualifier>Title</qualifier><payload>This is the <emphasize>Headline</emphasize>.</payload>'

TA G DESC RIP T IO N

<qualifier></qualifier> Specifies the title that appears above the headline. If you
omit this tag, the text HEADLINE will be used by default.

<payload></payload> Specifies the actual headline text.

<emphasize></emphasize> Applies the style to the text.

The Expression property must evaluate to the correct syntax. For example, looking back at the previous
example, the label hdl1Txt could be:

hdl1Txt: Label '<qualifier>The first headline</qualifier><payload>This is the <emphasize>Headline


1</emphasize>.</payload>';
Making headlines interactive
You can use the OnDrillDown trigger of a headline field to link the headline to more details or relevant
information about what is shown in the headlines. For example, if the headline announced the largest sales
order for the month, you could set up the headline to open a page that shows a sorted list of sales order for the
month.
The following code uses the OnDrillDown trigger to link Headline1 to the Dynamics 365 online help.

field(Headline1; hdl1Txt)
{
trigger OnDrillDown()
var
DrillDownURLTxt: Label 'https://go.microsoft.com/fwlink/?linkid=867580', Locked = True;
begin
Hyperlink(DrillDownURLTxt)
end;
}

Changing the visibility of headlines


You can use the Visible property to show or hide headlines that are defined on the HeadlinePar t page. With the
Visible property, you can show or hide the control either statically by setting the property to true or false , or
dynamically by using a Boolean variable.
Static visibility
With static visibility, you can simply set the Visible property on specific fields. For example, following code
hides Headline3 :

{
field(Headline1; hdl1Txt)
{

}
field(Headline2; hdl2Txt)
{

}
field(Headline3; hdl3Txt)
{
Visible=false;
}
field(Headline4; hdl4Txt)
{
}
}

By adding fields under Group controls, you can hide or show more than one headline by setting the Visible
property on the Group control. For example, the following code hides headings Headline3 and Headline4 :
group(Group1)
{
field(Headline1; hdl1Txt)
{
}
field(Headline2; hdl2Txt)
{

}
}
group(Group2)
{
Visible=false;
field(Headline3; hdl3Txt)
{
}
field(Headline4; hdl4Txt)
{
}
}

IMPORTANT
Unlike other page types, the group control has no effect on the UI on pages of type HeadlinePar t . Its primary purpose
is to enable developers to group headlines for controlling visibility.

Dynamic visibility
With dynamic visibility, you can show or hide a headline based on a condition that evaluates to true or false .
To dynamically show or hide a headline when the HeadlinePar t page opens, the headline field must be
in group control, and you set the Visible property on the group control to the Boolean variable that
determines the visibility. For example, you could add code on the page's OnAfterGetRecord trigger that
evaluates the relevance of displaying Headline3 and results in a Boolean variable being set to true or
false .

To dynamically show or hide a headline while a page is open, you set the Visible property on the field
control to the Boolean variable that determines the visibility.
group(Group1)
{
field(Headline1; hdl1Txt)
{
}
field(Headline2; hdl2Txt)
{

}
}
group(Group2)
{
// Determines visibility when the page opens
Visible=ShowHeadline3;
field(Headline3; hdl3Txt)
{
// Determines visibility while the page is open
Visible=ShowHeadline3;
}
field(Headline4; hdl4Txt)
{
}
}

See Also
Pages Overview
Page Object
Add Power BI Report Parts to Pages
2/6/2023 • 7 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave (v21) and later. For earliers versions, see Adding Power BI
Report Parts to Pages (Legacy).

Business Central integrates with Microsoft Power BI, enabling users to create Power BI reports based on
Business Central data. Users can view the reports from their Power BI workspaces, but also from the Business
Central client. For an overview about Power BI integration, see Business Central and Power BI.
Displaying a Power BI report in a Business Central page requires the page includes a Power BI Repor t part.
This part makes the connection to the Power BI Service, and lets users choose which report to display. Business
Central comes equipped with several pages that already include the Power BI Repor t part. For a list of these
pages, see Power BI FAQ.

Power BI Report part framework


The Business Central base application has many remote that provide the framework for Power BI integration.
You'll find these objects in the Applications\BaseApp\Source\Base Application.Source.zip\Power BI
framework folder of the installation media (DVD). But specifically, the main object for displaying Power BI
Repor t part on role centers and other pages is page 6325 "Power BI Embedded Report Part".
On roles centers, you'd typically use the part to display reports related to the user's role and daily activities. In
FactBoxes, you'd typically use it on list type pages to show reports related to selected records. A page can
include more than one Power BI Report part.
The "Power BI Embedded Report Part" page exposes several methods for controlling when the Power BI
Repor t part appears and the data it contains. The next sections include code examples of how to extend pages
with the Power BI Repor t part. You can also read more in the BCTech repo.

Add a Power BI Report part


To add a Power BI part to a page, you add a part control to the hosting page and associate it with page 6325
"Power BI Embedded Report Part" using the following syntax:

part(<part_name>; "Power BI Embedded Report Part")


{
}

For example, the following code adds a Power BI Report part to the Team Member Role Center page by using
a page extension.
pageextension 50101 TeamMemberRCPwrBiExt extends "Team Member Role Center"
{
layout
{
addfirst(rolecenter)
{
// Add the Power BI Report part on the role center page
part(PowerBIReportPart"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
}
}
}
}

The following code adds a Power BI Report part to the Sales Invoices List page by using a page extension.

pageextension 50100 SalesInvoicesListPwrBiExt extends "Sales Invoice List"


{
layout
{
addfirst(factboxes)
{
// Add the Power BI Report FactBox page as the first part in the
// FactBox area on the Sales Invoice List page
part("Power BI Report FactBox"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
}
}
}
}

Add a Power BI Report part that updates data based on selected


record
With Power BI Report parts in FactBoxes of list and card pages, in many cases you'll want the report to update to
display data that pertains to selected record on the page. You can implement this capability by using the
SetCurrentListSelection method of page 6325 "Power BI Embedded Report Part". The method has the
following signature:

Page."Power BI Report FactBox Part".PAGE.SetCurrentListSelection(InputSelection: Variant)

The InputSelection variant specifies the table field that uniquely identifies records in the list page. This field
should resolve to the primary key of the source table.
Example 1
This example extends the Sales Invoices page to include a Power BI Report part and uses the
SetCurrentListSelection method to use the update data in the report based on the primary key No. of the
Sales Invoice table.
pageextension 50100 SalesInvoicesListPwrBiExt extends "Sales Invoice List"
{
layout
{
addfirst(factboxes)
{
part("Power BI Report FactBox"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
}
}
}

trigger OnAfterGetCurrRecord()
begin
// Gets data from Power BI to display data for the selected record in the list
// based on the primary key, in this case the "No." field.
CurrPage."Power BI Report FactBox".PAGE.SetCurrentListSelection(Rec."No.");
end;
}

Add multiple Power BI Report parts


If you want to add more than one Power BI Report part to a page, where each part can display different reports,
you have to assign each part a context keyword. There are two ways to assign a context keyword, depending on
the page type.
Use SubPageView property
For role centers and other page types, you can use the SubPageView property of the part control that contains
the Power BI report part. In this case, the syntax for the adding a Power BI Report part is:

part(<part_name>; "Power BI Embedded Report Part")


{
SubPageView = where(Context = const('<context_keyword>'));
}

For example, suppose you wanted to add two Power BI Report parts to the Team Member Role Center page.
In this case, you could use the following code:
pageextension 50101 TeamMemberRCPwrBiExt extends "Team Member Role Center"
{
layout
{
addfirst(rolecenter)
{
part(PowerBIReportPart; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
SubPageView = where(Context = const('TeamMemberReportsPart1'));
}
part(PowerBIReportPart2; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
SubPageView = where(Context = const('TeamMemberReportsPart2'));
}
}
}
}

You can do the same for FactBoxes on list and card type page. For example, suppose you wanted to add two
Power BI Report parts in the FactBox of the Sales Invoices List . In this case, you could use the following code:

pageextension 50100 SalesInvoicesListPwrBiExt extends "Sales Invoice List"


{
layout
{
addfirst(factboxes)
{
part("Power BI Report FactBox 1"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports 1';
SubPageView = where(Context = const('DetailedSalesInvoiceReports1'));

}
part("Power BI Report FactBox 2"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports 2';
SubPageView = where(Context = const('DetailedSalesInvoiceReports2'));
}
}
}

trigger OnAfterGetCurrRecord()
begin
CurrPage."Power BI Report FactBox 1".PAGE.SetCurrentListSelection(Rec."No.");
CurrPage."Power BI Report FactBox 2".PAGE.SetCurrentListSelection(Rec."No.");
end;
}

Use SetPageContext method


For list and card type pages, another way to assign context keywords is to call the SetPageContext method of
the "Power BI Embedded Report Part" page.

procedure SetPageContext(InputContext: Text)

By calling SetPageContext , you can get the same results as you do with the SubPageView property. For example:
pageextension 50100 SalesInvoicesListPwrBiExt extends "Sales Invoice List"
{
layout
{
addfirst(factboxes)
{
part("Power BI Report FactBox 1"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports 1';

}
part("Power BI Report FactBox 2"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports 2';
}
}
}

trigger OnOpenPage()
begin
CurrPage."Power BI Report FactBox 1".PAGE.SetPageContext('DetailedSalesInvoiceReports1');
CurrPage."Power BI Report FactBox 2".PAGE.SetPageContext('DetailedSalesInvoiceReports2');

trigger OnAfterGetCurrRecord()
begin
CurrPage."Power BI Report FactBox 1".PAGE.SetCurrentListSelection(Rec."No.");
CurrPage."Power BI Report FactBox 2".PAGE.SetCurrentListSelection(Rec."No.");
end;
}

Display same set of Power BI reports on different pages


Suppose you want set up Power BI Repor t parts on different pages, where the parts have the following
behavior:
They show the same report selected by the user on all pages. When the user switches to another report on
one page, it will switch on all pages.
When a report is enabled or disabled in the Power BI Repor t part on one page, it's also enabled or disabled
in the parts on other pages.
To configure this functionality, you give each Power BI Repor t part on the different pages the same context
keyword. In other words, use the same values for the SubPageView property for the parts on all pages:

SubPageView = where(Context = const('<context_keyword>'))

Example 2
Suppose you want to display the same reports on the Sales Invoices page and Sales Orders page. In this
case, you could use the following line of code in both the Sales Invoices and Sales Orders pages, where
Sales is the common context identifier:
pageextension 50100 SalesInvoicesListPwrBiExt extends "Sales Invoice List"
{
layout
{
addfirst(factboxes)
{
part("Power BI Report FactBox"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
SubPageView = where(Context = const('sales'));
}
}
}

trigger OnAfterGetCurrRecord()
begin
CurrPage."Power BI Report FactBox".PAGE.SetCurrentListSelection(Rec."No.");
end;
}

pageextension 50101 SalesOrdersPwrBiExt extends "Sales Orders"


{
layout
{
addfirst(factboxes)
{
part("Power BI Report FactBox"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
SubPageView = where(Context = const('sales'));
}
}
}

trigger OnAfterGetCurrRecord()
begin
CurrPage."Power BI Report FactBox".PAGE.SetCurrentListSelection(Rec."No.");
end;
}

Limitations and behavior notes


The SubPageView property for the Power BI parts only supports constant values, not filters.
If you use both the SubPageView property and the SetPageContext method for specifying a context at the
same time, the SetPageContext value will overwrite the value specified in the SubPageView property.
Dynamically changing the context (for example, by calling SetPageContext in the OnAfterGetCurrRecord ) isn't
recommended and could lead to unexpected results.
Role center pages have no triggers, which means there's no way to call the SetPageContext method. As a
consequence, any Power BI part in the role center would have the same context: the current user's
profile/role.

See Also
Get Started with AL
Adding a FactBox to a Page
Pages Overview
Publishing and Installing an Extension
Adding a FactBox to a Page
2/6/2023 • 6 minutes to read • Edit Online

A FactBox is the area that is located on the right-most side of a page and it is divided into one or more parts that
are arranged vertically. This area is used to display content including other pages, charts, and system parts such
as Notes, and Links. Typically, you can use a FactBox to display information that is related to an item on the main
content page. For example, on a page that shows a sales order list, you can use a FactBox to show sell-to
customer sales history for a selected sales order in the list as shown below.

The following list highlights a few categories of FactBoxes:


Show related records/fields which are modeled as ListParts or CardParts.
Show related KPIs which are modeled as CardParts with charts or Cues. For more information, see Designing
Role Centers.
Visualize related data or display from external sources which are modeled as CardParts containing a Client
AddIn. For example, Bing maps, PowerBI, Microsoft Social Engagement, and more.

Adding a FactBox area to a page


You define the FactBox by adding a FactBox area container control to the page. The FactBox area control acts as a
placeholder to which you can add different parts for the FactBox. You can add a FactBox area control on the
following page types.
Card
Document
ListPlus
List
Worksheet

NOTE
Only one FactBox area control is allowed on a page.

WARNING
You can add a part to the FactBox area that displays an existing page of the CardPart or ListPart type only. If you attempt
to use another page type, you will get an error.

Example

page 50100 "Simple Customercard Page"


{
PageType = Card;

layout
{
area(FactBoxes)
{
part(MyPart; "Acc. Sched. KPI Web Srv. Lines")
{
ApplicationArea = All;
SubPageView = SORTING ("Acc. Schedule Name");
}
systempart(Links; Links)
{
ApplicationArea = All;
}
systempart(Notes; Notes)
{
ApplicationArea = All;
}
}
}
}

TIP
When used on Lists, FactBoxes can be used to show information about the entire list, or more contextually about the
user’s current selection; the currently selected rows. You can control the filter which gets passed to the FactBox that
determines its contextual contents.

System Parts
There are two system parts that you can define by using the systempart() keyword: Links and Notes :

VA L UE DESC RIP T IO N
VA L UE DESC RIP T IO N

Links Allows the user to add links to a URL or path on the record
shown in the page. For example, on an Item card, a user can
add a link to the supplier's item catalog. The links will appear
with the record when it is viewed. When a user chooses a
link, the target file opens.

Notes Allows the user to write a note on the record shown in the
page. For example, when creating a sales order, a user can
add a note about the order. The note will appear with the
item when it is viewed.

NOTE
The systempart keyword also includes an Outlook and MyNotes value, for example,
systempart(Outlook; Outlook) . These values are only supported by the Dynamics NAV Client connected to Business
Central (which has been deprecated after Business Central Spring 2019). These values are ignored in the Business Central
Web client.

Filtering data that is displayed on a page in a FactBox


In many cases, you want to change the content that is displayed on the page in the FactBox based on the content
of the main page. For example, if the main page is a Customer List, you can have a FactBox that includes the
Customer Details page that shows information about a customer. When a user selects a customer in the
Customer List, the Customer Details page displays information about the selected customer. To implement this
functionality, you set up a table filter that associates a field in the table that is used by the Customer Details page
with a field in the table that is used by the Customer List page, as shown in the example below. You can also filter
on a constant value or set of conditions.
Example
page 50101 "Simple Customerlist Page"
{
PageType = List;
SourceTable = Customer;

layout
{
area(content)
{
repeater(Control)
{
field("No."; "No.")
{
ApplicationArea = All;
}
}

area(FactBoxes)
{
part(CustomerList; "Customer Details FactBox")
{
ApplicationArea = All;
SubPageLink = "No." = FIELD ("No.");
}
}
}
}

Performance considerations
Having a page composed of multiple FactBox pages that each process data from different sources can degrade
performance. To improve responsiveness and the time it takes to load the page, Business Central 2020 release
wave 2 and later optimizes the sequence in which content is loaded. The sequence is as follows:
1. Content on the hosting page is loaded first, and users can immediately begin interacting with it.
2. The FactBox pane is loaded next, where each FactBox is loaded independently in sequence starting from the
top.
a. FactBoxes having the Visible property evaluate to false won't be loaded.
b. FactBoxes that aren't within view are only loaded when the user scrolls them into view. If the FactBox
pane is collapsed, no FactBoxes are loaded until the user expands the FactBox pane.
Below are some practical tips to help you make the most of this optimization:
Consider hiding any FactBoxes that represent secondary content that only some users will require. Learn
more about Choosing the Visibility of Parts.
For FactBoxes that require heavy processing, consider processing in the page background task. Learn more
about Using Page Background Tasks.
Avoid having triggers on the hosting page that call into a FactBox because this condition forces the FactBox to
ignore performance optimizations and load along with the content of the hosting page, adding to the total
loading time.
FAQ about performance
Are any FactBox triggers run when the FactBox is hidden?
No. The trigger is only run when the FactBox is visible and within the user's view.
How often are triggers run if the FactBox pane is expanded, collapsed, and then expanded again?
In this scenario, the OnOpenPage trigger is only run the first time. Once a FactBox is loaded, it isn't loaded again
for as long as the page remains open.
Are FactBoxes processed asynchronously?
No. This optimization is simply a controlled sequence in which triggers are run, still within the same session as
the hosting page. For more information about asynchronous processing in the background, see Designing page
parts for page background tasks.
Does this optimization work with SubPageLink or SubPageView properties?
The use of these properties has no effect on the sequence of loading content on a page. Using properties such
as SubPageView is preferred to writing trigger code to update a FactBox.
Does this optimization apply to parts that aren't FactBoxes?
This optimization doesn't apply to Role Center pages. When parts are used in the content area of a page, such as
on a Card page, they aren't loaded if their Visible property evaluates to false .
Can I force a FactBox to load along with page content?
There's no AL API to force FactBoxes to load along with the content of the hosting page.
Can I set the FactBox pane to start collapsed on all pages?
No. The default state of the FactBox pane is set by the Business Central platform and modifed by the user.
Does the experience vary on different browsers?
Each browser has its own definition of whether a FactBox is considered within view or not. For example, opening
Business Central in a new browser tab and quickly switching back to the original tab may pause loading of any
FactBoxes in the new tab.
Does this optimization apply to other form factors?
This applies to desktop, tablet, and phone clients.

See Also
Pages Overview
Page and Page Extension Properties Overview
Designing Role Centers
Using Designer
Arranging Fields on a Fasttab
Actions Overview
Field Arrangement on FastTabs
2/6/2023 • 3 minutes to read • Edit Online

FastTabs in Dynamics 365 Business Central allow users to find key information on a page by displaying the data
in separate groups. This article describes how individual fields are arranged on a FastTab and ways that you can
change the layout.
Organizing data using FastTabs helps users to find key information quickly, while at the same time giving an
overview of areas that otherwise would remain hidden. For example, the customer card page displays customer
information in the following categories: General, Communication, Invoicing, Payments, Shipping, and Foreign
Trade. Each category is a separate FastTab that can be expanded or collapsed, making it easier for users to focus
on one subject at a time. On task pages, a FastTab typically represents a single step in a task.

How fields are arranged on a FastTab of a page


By default, a FastTab is divided into two columns for containing fields. Fields are automatically distributed
between the left and right columns based on their order in the layout section of the page. Starting with the first
field in the Page Layout and working downward, fields are positioned in the left column and then in the right
column. The area that is occupied by the fields in each column is as equal as possible. Field captions are
positioned to the left of fields.

Pages automatically adjust to the available space on the screen. If horizontal space is reduced, a FastTab will
adapt and distribute fields into a single column. Similarly, a FastTab will automatically distribute fields into more
than two columns to take advantage of wider screens.

FastTab example
Creating a FastTab is easy. A FastTab is a group control directly within the content area of a card, document, or
task page. The following example shows how you can create a FastTab containing a pair of fields.
page 50101 SimpleCustomerCard
{
PageType = Card;
SourceTable = Customer;

layout
{
area(content)
{
group(GeneralFastTab)
{
CaptionML = ENU = 'General';

field(Name; Name)
{
ApplicationArea = All;
}
field(Address; Address)
{
ApplicationArea = All;
}
}
}
}
}

Collapsed or Expanded FastTabs


Dynamics 365 Business Central automatically determines whether FastTabs are initially displayed as expanded
or collapsed. For example, when a document page is opened the first time, the first two parts or FastTabs are
automatically expanded. All other parts or FastTabs are shown as collapsed to provide an optimal starting
experience. Users can change the state of a FastTab to be expanded or collapsed directly within the user
interface, but developers can't specify the starting state.

Choosing how to show fields in a FastTab


If a FastTab is expanded, you see all the fields. If it's collapsed, you just see the summary line. The summary line
is the header that displays a name for the group, such as 'Communication'. It can also include important fields
such as 'E-mail'. Promoting fields to the summary line enables you to present key information to the user, even
if the FastTab is collapsed. You can also specify fields that only appear when the users select the Show more
action on the FastTab. You promote a field or display it only when Show more is selected by setting the
Importance property of the field.

NOTE
If a group doesn't specify the CaptionML property or this is set to an empty value, it's considered to be a group used
only for structural purposes. This includes FastTabs. Structural FastTabs look and behave differently, for example, they can't
be collapsed by users unless they include the Show more action.

Organizing compound content in a FastTab


By using a Group control within a FastTab, you can group fields by similarity. This pattern also gives you control
over how fields are distributed between the left and right columns. When you group fields on a FastTab, the
groups are distributed evenly between the left and right columns. Fields aren't.
Similarly, page parts placed within a FastTab are distributed evenly between the columns. For example, a FastTab
containing two ListParts may be used to display two lists side by side for easier comparison. Learn more about
Page parts.

Manually arranging fields in multiple rows and columns


Using the GridLayout or FixedLayout controls, you can arrange fields in multiple rows and columns in a grid-like
format. These controls define a static layout that doesn't automatically adapt to the available space on the
screen. It's recommended to use these controls only when you're sure your users will access them on larger
screens. For more information, see Arranging Fields Using Grid and Fixed Controls.

See Also
Arranging Fields Using Grid and Fixed Controls
Pages Overview
Using Designer
Table in Dynamics 365 Business Central
Arranging Fields in Rows and Columns Using the
Grid Control
2/6/2023 • 3 minutes to read • Edit Online

By default, fields in a FastTab are arranged automatically in two columns that are based on the number of fields.
For more information, see Field Arrangement on a FastTab. You can use a Grid control or a Fixed control to
arrange fields in rows and columns on a page and design it to look like a grid-like format or a matrix-like
format. To understand the differences between the two controls to help you determine which control to use, see
Comparing Grid and Fixed controls.

NOTE
Grid control for arranging page fields is partially supported.

Using the Grid control, you can arrange the fields manually in one or more rows and columns. The Grid control
gives you the following options:
Set up your grid row-by-row or column-by-column.
Span a field across multiple rows and columns.
Show or hide field captions.

Setting-up fields in rows and columns in a FastTab


To set up a grid in row-by-row or column-by-column format, you define the Grid control in a FastTab of a page.
You must define the Grid control in a group and specify how you want to arrange the fields by using the
GridLayout property. For more information, see GridLayout Property.
Example
The following example demonstrates how to structure a page in a grid-like format.
page 50113 "Customers Page"
{
PageType = Card;
SourceTable = Customer;
layout
{
area(content)
{
group(General)
{
grid(MyGrid)
{
group("General Info")
{
field("No."; "No.")
{
ApplicationArea = All;
}
field(Name; Name)
{
ApplicationArea = All;
}
field("E-Mail"; "E-Mail")
{
ShowCaption = false;
ApplicationArea = All;
}
}
group("Address Details")
{
grid(Grid2)
{
group(GridForm)
{
field(Address; Address)
{
ApplicationArea = All;
}
field("Post Code"; "Post Code")
{
ApplicationArea = All;
}
}
}
}
}
}
}
}
}

The following screenshot shows how the resulting page looks like from the Web client.
Setting fields to span multiple rows and columns
You can set a field to span multiple rows or columns. When you set a field to span multiple rows, the field
occupies the cells in the rows below it, and existing fields in the occupied cells are moved to the right. When you
set a field to span multiple columns, the field occupies the cells in the columns to the left, and existing fields in
the occupied cells are moved to the right. You can also set a field to span multiple rows and columns.

IMPORTANT
The Dynamics 365 Business Central web client does not support row and column spanning for fields. If the page displays
in the Dynamics 365 Business Central web client, the fields appear without spanning.

For example, the following figure illustrates a Grid control that consists of six fields arranged in three rows.

If you set Field 2 to span two rows, then the following layout is displayed:

When you set a field to span multiple columns, the field occupies the cells in the columns to the right, and
existing fields in the occupied cells are moved to the right. Using the previous Grid example, if you set Field 2
to span two columns instead of two rows, the following layout is displayed:

You can also set a field to span multiple rows and columns. For example, if you set Field 2 to span two rows and
two columns, the following layout is displayed:
+
To set a field to span rows and columns
When you set the Grid control, the fields of that group can be set to span rows or columns.
To set a field to span one or more rows, set the value of the RowSpan property to the number of rows.
For more information, see RowSpan Property.
To set a field to span one or more columns, set the value of the ColumnSpan property to the number of
columns. For more information, see ColumnSpan Property.

NOTE
The RowSpan and ColumnSpan properties on fields in the grid layout are not supported in the Dynamics 365 Business
Central web client. The Rows layout on the grid control itself is not supported.

Hiding field captions


You can hide the caption of a group or a field. To hide the caption of a field, set the value of the ShowCaption
property to False . For more information, see ShowCaption Property.

See Also
Field Arrangement on FastTabs
Arranging Fields Using Grid and Fixed Controls
Arranging Fields in Rows and Columns Using the Fixed Control.
Arranging fields in rows and columns using the fixed
control
2/6/2023 • 3 minutes to read • Edit Online

By default, fields on a FastTab are arranged automatically in two columns based on the number of fields. For
more information on how the fields are placed on a page, see Field Arrangement on a Fasttab. To manually
arrange fields, you can either use a Grid control to design the page to look like a grid-like format, or a fixed
control to design the page to look like a matrix-like format. To understand the differences between the two
controls to help you determine which control to use, see Comparing Grid and Fixed controls.

IMPORTANT
Fields in a fixed layout are not editable even if the Editable property is set to true . However, if the field drills down to a
page where the field source is defined, then you can modify the field. For more information, see Editable Property.

How fixed control works


You use the fixed control to arrange page fields in rows and columns to form a matrix-like layout except that the
fixed control contains a specific number of fields, and a matrix can contain an unspecified number of fields. A
Fixed group control is typically used to display statistical data. The following illustration shows an example of a
page that uses a fixed control to show sales totals for different time periods.

You can also use a fixed control to display information in the details section of a Worksheet page. If you're using
the CRONUS International Ltd. demonstration database, then you can see examples of these uses in page 151,
Customer Statistics, and page 40, Item Journal.

Adding fields
You can add fields directly in the fixed control. However, when you add fields directly in the fixed control, all the
fields will display in an equal size and the larger fields will get compressed. The following illustration shows the
resulting field layout on a page.

Grouping fields in a fixed control


By placing the fields in a fixed control throughout a group control, you can define separate rows and columns to
create a matrix-like arrangement. The group control caption appears as the column header, and the field control
captions appear as the row headers. If you add two more group controls that contain fields, then the layout on
the page will display like a table format.
Example
The following AL code uses fixed control to display four fields on a page inside the group called Fixed Layout.

page 50114 "Fixed Control Example"


{
layout
{
area(content)
{
group("Fixed Layout")
{
fixed(DefiningFixedControl)
{
group("Group Caption")
{
field("Field 1"; "Field 1")
{
ApplicationArea = All;
}
field("Field 2"; "Field 2")
{
ApplicationArea = All;
}
field("Field 3"; "Field 3")
{
ApplicationArea = All;
}
field("Field 4"; "Field 4")
{
ApplicationArea = All;
}
}
}
}
}
}
var
"Field 1": Integer;
"Field 2": Integer;
"Field 3": Integer;
"Field 4": Integer;
}

The following illustration shows the resulting field layout on a page.

The group control caption appears as the column header, and the field control captions appear as the row
headers. If you add two more group controls that contain fields, then the layout on the page will resemble the
following illustration.
NOTE
Only the captions of fields in the first column define the row headings. Therefore, only the field captions for the first group
control appear. The field captions in other group controls are ignored.

Using multiple fixed controls


You can also set up more than one fixed control in a group control. The page area will then divide the fields into
two columns that contain the separate fixed fields. For example, the following illustration shows the page layout
if you have four fixed controls.

NOTE
The fields in the fixed controls in the illustration are not in a group control. If they were in a group control, then they
would follow the same principle as described in the previous section about how to group fields.

IMPORTANT
In previous versions, having a fixed control directly under a content area was supported. However, in Dynamics 365
Business Central, you must make sure that the fixed control is nested in a Group control. For more information, see
Supported Structure for Using the Grid and Fixed Controls.

See Also
Field Arrangement on a FastTab
Pages Overview
Arranging Fields Using Grid and Fixed Controls
Arranging Fields in Rows and Columns Using the GridLayout Control
Field Groups (DropDown Controls)
2/6/2023 • 2 minutes to read • Edit Online

A field group in table or table extension objects defines the fields to display in a drop-down control on pages
that use the table.
In a table object, you define field groups by first adding a fieldgroups control, and then adding one or more
fieldgroup(<Name>; <Field>) keyword for each group, where:

<Name> can be either DropDown , for adding fields to the drop-down control, or Brick to display data as tiles.
<Field> is a comma-separated list of the fields, by name, to include in the group.

NOTE
A field group can also be used to specify fields that display when list type pages are shown in the tile view. For more
information, see Displaying Data as Tiles.

fieldgroups
{
fieldgroup(DropDown; Field1, Field2)
{

}
fieldgroup(Brick; Field1, Field2)
{

}
}

NOTE
The fieldgroups keyword cannot be inserted before the key control.

IMPORTANT
The syntax for using a DropDown, must be exactly DropDown with the right capitalization.

In a table extension object, the fieldgroups control allows you to add more fields to a field group defined for
the table object. This can be done by using the addlast(<name>; <field>) keyword.

WARNING
The server will remove the duplicates, if multiple extensions attempt to add the same field more than once. A field can
only be added to the field group once.

Add fields for a drop-down control


You add a field to include in a drop-down control by using the DropDown field group name in the keyword.
NOTE
Adding a new fieldgroup to a table extension is not possible.

The following example illustrates how to add the field

tableextension 50100 CustomerExercise extends Customer


{
fields
{
field(50100; "V02Max"; Decimal) { }
}

fieldgroups
{
addlast(DropDown; V02Max) { }
}
}

See Also
Debugging in AL
Developing Extensions
Microsoft .NET Interoperability from AL
Field Calculation Methods
2/6/2023 • 5 minutes to read • Edit Online

The following methods perform various actions on fields:


CalcFields
CalcSums
FieldError
FieldName
Init
TestField
Validate

CalcFields method
CalcFields updates FlowFields. FlowFields are automatically updated when they are the direct source expressions
of controls, but they must be explicitly calculated when they are part of a more complex expression. For more
information about Flowfields, see FlowFields.
CalcFields has the following syntax.

[Ok :=] Record.CalcFields(Field1, [Field2],...);

When you use FlowFields in AL methods, you must use the CalcFields method to update them.
In the following example, the SETRANGE method sets a filter and then the CalcFields method calculates the
Balance and Balance Due fields by using the current filter and performing the calculations that are defined as the
CalcFormula properties of the FlowFields. This example requires that you create the following variable.

VA RIA B L E DATA T Y P E SUBT Y P E

Customer Record Customer

Customer.Get('01454545');
Customer.SetRange("Date Filter",0D,TODAY);
Customer.CalcFields(Balance,"Balance Due");
Message('The Balance is %1 and your Balance Due is %2',Customer.Balance,Customer."Balance Due");

The following message is displayed:


The Balance is 342,529.44 and your Balance Due is 342,529.44

CalcSums method
CalcSums calculates the sum of one or more fields that are SumIndexFields in the record.
CalcSums has the following syntax.

[Ok :=] Record.CalcSums (Field1, [Field2],...);


For CalcSums, a key that contains the SumIndexFields must be selected as the current key. Similar to CalcFields,
CalcSums uses the current filter settings when it performs the calculation.
In the following example, an appropriate key is selected, some filters are set, the calculation is performed and
then a message is displayed. This example requires that you create the following variable.

VA RIA B L E DATA T Y P E SUBT Y P E

custledgerentry Record Cust. Ledger Entry

custledgerentry.SetCurrentKey("Customer No.");
custledgerentry.SetRange("Customer No.",'10000','50000');
custledgerentry.SetRange("Posting Date",0D,TODAY);
custledgerentry.CalcSums("Sales (LCY)");
Message('%1 calculated sales',custledgerentry."Sales (LCY)");

FieldError method
FieldError triggers a run-time error after it displays a field-related error message.
FieldError has the following syntax.

Record.FieldError(Field, [Text]);

This method is very similar to the Error method. However, in the FieldError method, if the name of a field is
changed, for example, translated to another language, in the Table Designer, the message from the FieldError
method will reflect the current name of the field.
The following examples show how to use the FieldError method. These examples require that you create the
following variable.

VA RIA B L E DAT E T Y P E SUBT Y P E

Item Record Item

Item.Get('70000');
If Item.Class <> 'HARDWARE' then
Item.FieldError(Class);

If item 70000 has a Class other than HARDWARE, then you receive the following error message:
Class must not be OTHER in Item No. ='70000'.
If the text or code field contains the empty string, then you receive the following error message:
You must specify Class in Item No.='70000'.
If the field is a numeric field and is empty, it is treated as if it contains the value 0 (zero), and then you receive the
following error message:
Class must not be 0 in Item No.='70000'.
You can change the default text that is displayed in the error message. The following example shows how to use
the FieldError method and change the default text. This example requires that you create the following variable.
VA RIA B L E DATA T Y P E

Class Code

if Item.Class < '4711' then


Item.FieldError(Class,'must be greater than 4711');

The following error message is displayed:


Class must be greater than 4711 in Item No.='70000'.

FieldName
FieldName returns the name of a field. It has the following syntax.

Name := Record.FieldName(Field);

You could just use the name of the field. However, using FieldName lets you create messages that always contain
the name of the field, even if the name of the field is changed.
This example shows how to use FieldName together with FieldError.

FieldError(Quantity,'must not be less than ' + FieldName("Quantity Shipped"));

Init
Init initializes a record. It has the following syntax.

Record.Init();

If a default value for a field has been defined by using the InitValue property, this value is used for the
initialization. Otherwise, the default value of each data type is used.

NOTE
Init does not initialize the fields of the primary key.

TestField method
TestField tests whether a field contains a specific value. It has the following syntax.

Record.TestField(Field, [Value]);

If the test fails, that is, if the field does not contain the specified value, an error message is displayed and a run-
time error is triggered. This means that any changes that were made to the record are discarded. If the value that
you test against is an empty string, the field must have a value other than blank or 0 (zero).
The following example tests the Language Code field for customer number 10000 in the Customer table and
tests whether the Language Code is ZX. This example requires that you create the following variable.
VA RIA B L E DATA T Y P E SUBT Y P E

customer Record Customer

customer.Get('10000');
customer.TestField("Language Code",'ZX');

Validate method
Validate calls the OnValidate trigger of a field. It has the following syntax.

Record.Validate(Field [, NewValue]);

When you enter an account number in a ledger, code in a table trigger is executed to transfer the name of the
account from the chart of accounts. If you enter an account number in a batch job, the code which transfers the
name of the account is not automatically executed. The following example executes the appropriate field-level
trigger code. This example requires that you create the following variable.

VA RIA B L E DATA T Y P E SUBT Y P E

GeneralLedgerEntry Record G/L Entry

GeneralLedgerEntry.Validate("G/L AccountNo", '100');

This corresponds to the following code.

GeneralLedgerEntry."G/L AccountNo" := '100';


GeneralLedgerEntry.Validate("G/L AccountNo");

The Validate method is useful for centralizing processing, which makes your application easier to maintain.
For example, if the OnValidate trigger of the Total Amount field performs a calculation that uses values from
three other fields as operands, the calculation must be performed again if the contents of any one of these fields
changes. You should avoid entering the calculation formula in the OnValidate triggers of each field because this
can create errors if the calculation formula has to be changed later and you have to update the code in all the
triggers. Instead, you should enter the calculation formula in the OnValidate trigger of only one of the fields and
call this trigger code from the OnValidate triggers of the other fields.

See Also
AL Methods
Formatting Decimal Values in Fields
2/6/2023 • 5 minutes to read • Edit Online

This article describes how you can format the decimal values that appear in fields on table, pages and reports.
For example, you can change how the data appears in a Cue on the Role Center page. To format data, you use a
combination of the AutoFormatType Property, AutoFormatExpression Property, and DecimalPlaces Property of
the field. These properties work together to enable you to specify the following:
Display amounts and unit amounts in another currency.
Specify the number of decimal places.
Specify whether to display a thousand separator.
Specify characters before and after the value, such as currency signs or %.

Implementation overview
When a field is used on a page or report, you can set the AutoFormatType and AutoFormatExpr properties
directly on the page field or report field (column), or you can set them on the underlying table field. If you
specify the properties on the table field, then the format applies wherever the field is used. Specifying the
properties on the page or report field will only apply the format to the specific page or report. If you specify the
properties on the table field and the page or report field, then the settings on the page or report field take
precedence.
When you use the AutoFormatType and AutoFormatExpression properties to format a field, two events are
raised by the system codeunit 45 Auto Format : OnResolveAutoFormat and OnAfterResolveAutoFormat.

Setting up data formatting


The settings for the AutoFormatType , AutoFormatExpression , and DecimalPlaces properties will depend
on the type of data that is displayed, for example, this could be currency amounts, unit amounts, simple
decimals, or ratios. For the most part, the AutoFormatType property is the primary setting, which in turn
determines the options for setting the DecimalPlaces and AutoFormatExpr properties.
If the AutoFormatType is not set or is set to an incorrect property value, then the default setting is used,
regardless of whether the AutoFormatExpression or DecimalValues properties are set. The default setting
uses AutoFormatType = 1 and AutoFormatExpression = '' .
The following tables describes how to set each of the properties to achieve the format that you want.

Setting the DecimalPlaces property


With the following set up, the AutoFormatExpression property is ignored.

A UTO F O RM AT T Y P E P RO P ERT Y DEC IM A L P L A C ES P RO P ERT Y USA GE DESC RIP T IO N


A UTO F O RM AT T Y P E P RO P ERT Y DEC IM A L P L A C ES P RO P ERT Y USA GE DESC RIP T IO N

0 Set to the number of decimal places Use this configuration when you want
that you want to display for the value. to format the decimal value according
the Standard Format 0 (which is the
default format) with a specific number
of decimal places.

For example, if the value is a US


decimal -76543.21 and you set the
DecimalPlaces property to 0 , then
the value appears as 76,543 . The
properties will look like this:

AutoFormatType = 0;
DecimalPlaces = 0;

Setting the AutoFormatExpression property


With the following setup, the DecimalPlaces property is ignored.

A UTO F O RM AT T Y P E P RO P ERT Y A UTO F O RM AT EXP RESSIO N P RO P ERT Y USA GE DESC RIP T IO N

1 Set to return a currency code, such as Use this configuration when you want
USD or IDR. The blank currency code to format the data as an amount. For
'' denotes LCY and is the default example, a sales order will use two
value. decimals when the currency is defined
as US dollar and no decimals when the
currency is defined as IDR (Indonesian
rupiah). For example:

AutoFormatType = 1;
AutoFormatExpression = 'IDR';

2 Set to return a currency code such as This is similar to the previous


USD or IDR. The blank currency code configuration where the
'' denotes LCY and is the default AutoFormatType property is set to
value. 1 , except you use this configuration
when you want to format the data as a
unit amount.
A UTO F O RM AT T Y P E P RO P ERT Y A UTO F O RM AT EXP RESSIO N P RO P ERT Y USA GE DESC RIP T IO N

10 Set to the property according to the Use SubType 1 to add the currency
following syntax: symbol and use the amount type
precision. You use SubType 2 for unit
'[SubType][,<currencycode or amount precision. For example, set the
expression>[,<PrefixedText>]]'
property to '1,USD' to add the $
symbol, like $543.21 .
SubType can be 1 , 2 , another
number, or omitted: AutoFormatType = 10;
AutoFormatExpression = '1,USD';
1 sets the value to an amount type
(see 1 above). 2 sets the value to a If you omit the SubType, you can use
unit amount type (see 2 above). The this configuration to customize the
syntax for these two settings is: format based on one of the standard
formats. This option enables you to
'SubType,<currencycode[,
<PrefixedText>]'
specify characters before and after the
decimal value, such as currency signs $
and percent %.
If you omit the subtype or use a
number other than 1 or 2, the syntax
For example, if you want to prefix the
is:
decimal value with a $ , include a
thousand separator, and have a
'<CustomNumber>, <expression>[,
<PrefixedText>]' maximum of two decimal places, such
as $76,453.21 , then you can set the
where <expression> sets the properties to:
precision and one of the standard
AutoFormatType = 10;
formats. For more information, see
Standard Formats. AutoFormatExpression =
'$<precision, 2:2><standard
format, 0>'

If you want to display the decimal


value as a percentage, then you can
add % at the end of the setting. For
example:

AutoFormatType = 10;
AutoFormatExpression =
'<precision, 1:1><standard
format,0>%'

When you include a % at the end of


the setting, then the decimal value is
assumed to be the ratio, and the
decimal value will be multiplied by 100.
For example, a value of 0.98 will be
formatted to 98%.

11 Set the property to the standard Use this option when you want full
format as explained below. For control over the formatting. The
example: format string will be applied exactly as
specified in the AutoFormatExpr
'<Precision,3:3><Standard property.
Format,0>'

Precision
The precision determines the minimum and maximum number of decimal points for values. The precision takes
the format <precision,minimum:maximum> . For example, <precision,minimum:maximum> sets the data with a
minimum of 2 and a maximum of 3 decimal places.
Standard formats
The following table describes the standard formats that are available for the AutoFormatExpr property when
the AutoFormatType property is set to 10.

STA N DA RD F O RM AT F O RM AT DESC RIP T IO N EURO P E DEC IM A L EXA M P L E US DEC IM A L EXA M P L E

0 <Sign><Integer -76.543,21 -76,543.21


Thousand><Point or
Comma><Decimals>

1 <Sign><Integer><Point or -76543,21 -76543.21


Comma><Decimals>

2 <Sign><Integer><Point or -76543.21 -76543.21


Comma><Decimals>

3 <Integer Thousand><Point 76.543,21- 76,543.21-


or Comma><Decimals>
<Sign>

4 <Integer><Decimals> 76543,21- 76543.21-


<Point or Comma><Sign>

9 XML format -76543.21 -76543.21

See Also
AutoFormatType Property
AutoFormatExpression Property
DecimalPlaces Property
Actions overview
2/6/2023 • 7 minutes to read • Edit Online

In Dynamics 365 Business Central, actions are displayed at the top of each page, referred to as the action bar. In
this article, you learn about different types of actions, and how you can enable users to quickly locate the actions
they want to use.
The actions can be displayed in different menus on the action bar.

You can choose from the following action menus to place the actions in the specified area.

A REA SY N TA X USED O N DESC RIP T IO N EXA M P L E

Actions menu area(processing) Role Center, list, card, User tasks Post a sales order
and task pages

New document area(creation) List, card, Role Center Actions that appear New sales invoice
group in Actions pages, and task under the New
menu pages group. Opens a new
Dynamics 365
document.

Navigate menu area(navigation) List, card, and task Links to other pages Prices
pages in Dynamics 365
Business Central.

Report menu area(reporting) Role Center, list, card, A list of available Customer Top 10 List
and task pages reports.

The following actions are related to the Role Center page.

A REA SY N TA X USED O N DESC RIP T IO N EXA M P L E

Navigation menus area(sections) Role Center pages The top-level Posted sales invoices
navigation consists of
one or more root
items that expand to
display a submenu of
links to other pages.

Navigation bar area(embedding) Role Center pages The second-level Customers


navigation displays a
flat list of links to
other pages.
For more information about actions used on the role center page, see Designing Role Centers.

Types of Actions
TIP
If you used to work in Microsoft Dynamics NAV, you can get an overview of the mapping between actions in the
Differences in the Development Environments topic.

Each page has a different set of actions depending on the page type, and the processes that the page supports.
In order to create the appropriate set of actions for a particular page, you should have a good understanding of
your customer's business processes.
Each process in an organization has several actions associated with it. You should try to create a full set of
actions that mirror all tasks and processes that are performed.
For example, the Sales Orders list page at CRONUS International contains all actions related to processing sales
orders. During user configuration and personalization, some of these actions may be hidden or promoted to the
ribbon. Therefore, you must create a full set of actions for the customer.

NOTE
With Business Central 2022 release wave 2, the way that you promote actions on pages or page extensions has changed.
Promoting actions is defined in a specific section of the page definition and contains a reference to the action. For more
information, see Promoted Actions.

Pages can have the following actions as described in each section below.

Actions menu
The Actions menu is a displayed in the action bar on all page types, and contains relevant tasks for the current
page. Typically, you add processing tasks and creation tasks in the Actions menu. To add processing actions such
as posting a sale order, you must use the processing action area. They're regular daily tasks. Therefore, they
must be on the Actions menu. For examples on how to add actions to the Actions menu, see Adding Actions to a
Page.
Some examples from the Customer page are as follows:
Sales Invoice
Sales Quote
Sales Credit Memo
Ledger Entries
Invoice Discounts
Prices
Line Discounts
You can add actions to the Actions menu, group actions together under action sub menus, or promote them to
the ribbon. For examples of how to use actions, see Page Object and Page Extension Object.
New Document menu
The New Document menu is often displayed both as a top-level menu in the actions bar and as a sub menu in
the Actions menu. You can use this menu to open new documents within Dynamics 365. You can add an action
to create a new document such as creating a new sales invoice. This action displays in a separate menu called
New document in the Actions menu. To add to the New document menu, you must use the creation action
area.
For example, on the Customers page, if the order processor wants to create a new invoice, the order processor
can open the new page directly from the Actions menu, which is useful when creating new sales invoices daily.

Navigate menu
The Navigate menu is displayed after the Actions menu in the action bar. Rather than providing tasks for the
user, this menu provides additional information by taking the user to a specific page in Dynamics 365. To add a
page link in the Navigate menu, you must use the navigation action area. These actions act like a bookmark to
enable quick access to view a page.

NOTE
You should not add a Navigation action to a Role Center page.

Report menu
The Report menu is displayed after the Navigate menu in the action bar. The Reports menu lists the reports
most relevant to a page. If a user doesn't require a Report menu, then the menu is hidden. Sometimes it's
relevant to promote the most important reports to the top-level in the action bar to save the user from too
many clicks. To create an action in the Report menu, you must use the reporting action area.

Promoted Actions
NOTE
With Business Central 2022 release wave 2, the way that you promote actions on pages or page extensions has changed.
Promoting actions is defined in a specific section of the page definition and contains a reference to the action. For more
information, see Promoted Actions.

Promoted actions are actions that are set up on the Actions, Navigate, or Reports menus in the action bar, but
are also configured to display in custom menus in the action bar. Although the actions are set up on the Actions,
Navigate, or Report menus, you can choose to hide them on these menus and only show them in custom
menus. Promoted actions can be used on Card, Document, List, ListPlus, and Worksheet pages to provide quick
access to common tasks that appear under the Home tab.

Run Power Automate flows from page actions


APPLIES TO: Business Central 2022 release wave 2 and later

With Business Central 2022 release wave 2, it's possible to define page actions that trigger a Power Automate
instant flow by using custom actions. Custom actions are defined next to other actions, but use the
customaction keyword instead. The syntax is as follows:
customaction(MyFlowAction)
{
CustomActionType = Flow;
FlowId = '<the-GUID-identifying-the-Power-Automate-Flow>';
FlowEnvironmentId = '<the-GUID-identifying-the-Power-Automate-environment>';
}

For a customaction , the CustomActionType Property must be set to Flow . The FlowId Property and the
FlowEnvironmentId Property must specify the IDs of the flow and the environment of the flow. These properties
make up the target flow identity, allowing the client to trigger the flow when the custom action is invoked.

TIP
You can get the flow and environment IDs in Power Automate. Sign in to Power Automate and open the flow for editing.
Then, get the environment ID and flow ID from the URL in the browser address, which has a format like:
https://make.powerautomate.com/environments/<environment ID>/flows/<environment ID> .

To learn more about Power Automate flows with Business Central, see Power Automate Integration Overview.

Grouping Actions in Submenus


Within the different areas, you can create submenus to a group of actions and improve navigation. You create a
submenu by adding a group() control, as shown in the following example:

actions
{
area(Report)
{
action(Report 1)
{
RunObject = report "Report1";
}

// Adds a submenu called "Group1" to the Report menu.


group(Group1)
{
// Adds the action "Report 2" to the My Label submenu.
action(Action2)
{
RunObject = report "Report2";
}
// Adds a submenu called "Group2" to the Group1 submenu.
group(Group2)
{
// Adds the action "Report 3" to the Group1 submenu.
action(Action3)
{
RunObject = report "Report3";
}
}
}
}
}

NOTE
Prior to Dynamics 365 Business Central 2019 Wave 2, in the client, submenus were automatically placed before single
actions on the same level. This means, for example, group Group2 appears before the action Repor t 2 .
Actions at runtime
An action can trigger code to run, such as posting a document or otherwise modifying a record in a table. When
a user chooses an action, one of the following pieces of logic will happen in addition to the code that the action
itself triggers:
If the page is empty and no longer shows any records, the page is reinitialized with default values.
If the page does show records, and the current state is within the page filters boundary, the
OnAfterGetRecord trigger is run on the page.
If the current record that the page showed is now outside the filter but there are other records within the
filter, the OnFindRecord trigger is called, and the OnAfterGetRecord trigger is run on the next record
with the given filters.
The logic runs in the transaction that the action triggered. This can cause the application code to result in users
locking the whole table when they thought they were only modifying one record.
To avoid users accidentally locking tables, you can use the SetSelectionFilter method before your code passes
the record variable to the processing codeunit, for example. The following code example illustrates the code on
the OnAction trigger on an action on a page.

if confirm('Are you sure you want to call this codeunit?', true) then begin
CurrPage.SetSelectionFilter(Rec);
codeunit.Run(50000, Rec);
end;

See Also
AL Development Environment
Developing Extensions in AL
Pages Overview
Promoted Actions
Adding actions to a page
2/6/2023 • 6 minutes to read • Edit Online

This topic shows how to create new actions, how to add actions to a page, and how to preview them in the
Dynamics 365 web client. In Dynamics 365, actions can be displayed in the action bar of all pages and grouped
together under the following actions menus:
Promoted action categories (legacy)
Actions
Navigate
Report

NOTE
With Business Central 2022 release wave 2, the way that you promote actions on pages or page extensions has changed.
Promoting actions is defined in a specific section of the page definition and contains a reference to the action. For more
information, see Promoted Actions.

Before putting an action on a page you should think about the business processes that the action supports. For
example, on page 42, the Sales Orders list page, the Actions button contains actions for all tasks related to
processing sales orders. Creating these actions can make it easier for the order processor to perform their daily
tasks, such as posting sales orders and creating new customer orders.
For more information about different types of actions and where to use them, see Actions Overview.

TIP
After you have added actions to a page, you can use Designer to alter the actions, like moving an action to or from a
promoted category, hiding and action or action group, and more. For more information, see Using Designer.

To add Actions to a Page


The page actions are displayed on the header section. There are multiple tabs to help navigate to the right item.
In order to add actions to the action bar, you must use the keywords with Anchors or Targets. These keywords
are used to place and move the actions around in the tab groups. For more information about adding, moving,
and modifying actions, see Using Keywords to Place Actions and Controls.

NOTE
Actions can only be linked to a page, or to a group control. Actions cannot be linked to fields, or parts on a page.

Set an icon to an action


Dynamics 365 Business Central includes images that you can use on actions in command bar menus and
promoted actions on the ribbon. To add an image to an action, you add the Image property and you must
provide the name of the image you that want to use from the Dynamics 365 Business Central Action icon
library. By default, the size of images is 16 pixels high by 16 pixels wide. For promoted actions, you can choose
to display larger images that are 32 pixels high and 32 pixels wide. For more information, see Image Property.
Example
The following example shows how to use different action areas on a page object of the PageType Card .
These actions will display in the following menus in the action bar. The following example uses the legacy syntax
for promoted actions. For more information, see Promoted Actions.
1. Actions menu: The area(Processing) action area is used to display the action in the Actions menu. This action
uses the Promoted and PromotedCategor y properties in order to display the action in the promoted
actions menu called Process .
2. New Document group: The area(Creation) action area is used to display the action in the New document
group in the Actions menu. Also, this action uses the Image property to display a form icon instead of a
default icon.
3. Navigate menu: The area(Navigation) action area is used to display the action in the Navigate tab. This
action and other actions in this example uses the RunObject property to assign a page to the action.
4. Report menu: The area(Reporting) action area is used to display this action in the Report menu, and also a
Group control is added as a submenu to this menu. It sets the Caption property to make the action group
visible in the Reports menu.
page 50110 PageName
{
PageType = Card;

actions
{
// Adds the action called "My Actions" to the Action menu
area(Processing)
{
action("My Actions")
{
Promoted = true;
PromotedCategory = Process;
ApplicationArea = All;
trigger OnAction()
begin
Message('Hello World');
end;
}
}

area(Creation)
{
// Adds the action "My New document" to the New Document group in the Actions menu.
action("My New document")
{
ApplicationArea = All;
RunObject = page "Customer Card";
Image = "1099Form";
}
}

area(Navigation)
{
// Adds the action called "My Navigate" to the Navigate menu.
action("My Navigate")
{
ApplicationArea = All;
RunObject = page "Customer Card";
}
}

area(Reporting)
{
// Adds a submenu called "My Label" to the Report menu.
group(NewSubGroup)
{
Caption = 'My label';
group(MyGroup)
{
// Adds the action "My Report" to the My Label submenu.
action("My Report")
{
ApplicationArea = All;
RunObject = page "Customer Card";
}
}
}
}
}
}
NOTE
Actions can be assigned to a page by setting the RunObject property, or by adding a trigger to a Codeunit. For more
information, see RunObject Property and Codeunit Triggers.

The promoted action menus are always displayed first so the promoted actions provide quick access to common
tasks, and users don't have to browse through a menu to access them. Add the Promoted property to add
actions to the promoted action menu. For more information on how to add promoted actions, promoted
categories, and examples, see Promoted Actions.
You can assign different icons for your actions from the Dynamics 365 image library. For more information, see
Image Property.

Set up a keyboard shortcut on an action


You can use the ShortcutKey property to add a keyboard shortcut to an action. Pressing the key that you set up
with this property provides the same result as selecting the action. For example, the following code adds the
shortcut Shift+Ctrl+D to an action:

action(DoThisAction)
{
ApplicationArea = All;
ShortCutKey = 'Shift+Ctrl+D';

trigger OnAction()
var
begin
DoThis();
end;
}

NOTE
Actions are used in different contexts to drive different experiences in the user interface. Be aware that keyboard shortcuts
are not supported across all contexts. For example, the ShortcutKey property is not supported for actions defined in
area(sections) or area(embedding) .

To help you design shortcuts, keep the following information in mind:


Some shortcuts have default assignments, either defined by the platform or in the base application. Don't
reuse shortcuts that are already assigned for different purposes. For a list of these shortcuts, see
Keyboard Shortcuts for the Dynamics 365 Business Central Web Client. Try to be consistent with
shortcuts used across pages, reusing shortcuts for similar actions.
Web browsers also support a set of default shortcuts. The shortcuts that you set with the ShortCutKey
property take precedence and will override the similar shortcuts of the web browser.
You can also set up shortcuts on actions of pages contained in parts of the main page. In this case, the
shortcuts only work when the user has focus on the part that contains the page. Consider the following
behavior when a user presses a shortcut while a page part's in focus:
If a shortcut's not defined on the page in the focused part but is defined on the main page, the main
page's action will be triggered.
If a shortcut's defined on the page in the focused part and the main page, the focused part's action is
triggered. Shortcut's defined in the part take precedence.
See also
Actions Overview
Pages Overview
Promoted Actions
Actions in the user interface
2/6/2023 • 5 minutes to read • Edit Online

This article provides guidelines for organizing actions when creating, extending, and customizing pages in
Business Central. The guidelines follow the principles and precedence of Microsoft 365 applications, such as
Outlook, with the primary goal of providing a familiar and efficient command presentation to the Business
Central users.

Pages and actions


Pages make up the user interface in Business Central and frame the activities and tasks that users have,
supported by the actions defined in the pages. Almost all pages present a combination of system actions, which
are the common actions that are found on many pages, such as Edit , View , and Delete , and application actions,
which are unique actions defined and developed for each page, such as Post on document pages.
With the desktop user interface to Business Central, actions are available to the user in several places on a page.
An action's placement reflects its scope and importance among the total set of actions. Most important are the
actions in the action bar appearing prominently at the top of a page, close to the page title. Here, the action bar
combines system actions, application actions, and the various toggles for panes and panels, such as the Factbox
pane, to form the command presentation for the page-level.

Page -level actions


Page-level actions are the actions in a page whose scope and effect the user understands in relation to what the
whole page stands for. For example, with a document page that is a sales invoice, the scope of the Post action is
the whole document, making that a page-level action. A page-level action may allow or expect the user to make
a selection in the page that sets or limits the scope of the action, such as when the Post action in a list assumes
the user has selected an invoice to Post.
Part-level actions
In addition to actions at the page-level, each part on a page may have specific actions available to the user for
managing and working with that part. For example, the Lines section on a document has both system and
application actions whose scope the user understands to be exclusively the document lines and which appears
to the user within the Lines section. Similarly, Factboxes can define actions specific to their functionality that the
user reaches in an action menu on the Factbox.
Application actions
Achieving a great user experience starts with organizing the page-level actions to suit users’ needs and
expectations. Consider the tasks that users have with the page, the type of page you place actions in, and the
total set of actions in the page. In the following, we describe these considerations in more detail.
Consider the tasks that users have on a page
The most important question when planning and developing application actions for a page is “what is the user
achieving in this page, and how can the page’s actions support that best?” Next, as you answer that question and
start placing actions on the page to support a task, give prominence to actions that typically start or end the
task in the user’s understanding. On the other hand, actions that users generally need for a task only in certain
cases can be given a less prominent placement.
Consider the type of page you place actions on
Business Central has a set of page types that are well suited to support the range of tasks that business users
have. Knowing the Business Central page types and their recommended uses is important to place application
actions where users expect it and in a way that is consistent with how similar actions appear in other pages.
Check out the section about Business Central Page Types and Layouts to learn about the concepts that the Action
Bar guidelines build upon.
Consider the total set of actions on a page
Each action in a page is sharing users’ attention with all the actions on the page. When there’s just a few actions
on a page, it usually works well to place those actions together at the same level, and without grouping them.
When the number of actions in a page goes up, grouping them in a natural way for the user gets increasingly
important.
Solve distractions, not discoverability
As you lay out actions on a page, making the right set of actions appear prominent is important to increase the
likelihood that users discover them. In cases where users have difficulty discovering the right action on a page,
consider solving this by removing the distraction that less important actions may be causing. For example, if
possible, by placing the less important actions in a separate group, so the actions you want to emphasize stand
out more.

Common application actions and groups


Some application actions and action groups repeat on several pages in Business Central, such as Statistics ,
Post , and many more. While these actions and groups have an individual implementation on each page they
appear, they bear the same caption and icon across pages. This helps users understand the commonality of
these actions and makes them recognizable across pages in a way equal to that of system actions, such as Share
and Bookmark.
Business Central defines several common actions and action groups as part of the standard application
functionality. In addition, extensions and apps define custom actions and groups to support their functionality. To
support users as they learn and use common application actions, it's important that actions named similarly
also behave similarly. Furthermore, having a consistent placement of common actions in certain groups in the
action bar makes it efficient for users to remember and find the actions.
When you add custom application actions to Business Central, consider the established common action and
action groups. A custom action that complements existing common actions should have a caption and
placement that makes it easy for Business Central users to reuse their knowledge about the existing actions. If
you're adding custom actions that work differently from the existing common actions, then avoid using captions
and placement that suggest a similarity that isn't there.

Split button groups


It's possible to show an action group as a split button to get better discoverability and one-click access to the
first action in the group. Show an action group as a split button when the actions in the group are connected by
the effect they have. For example, a split button is relevant to consider for a group with the actions Correct,
Cancel, and Create corrective credit memo, since these three actions achieve variants of the same result, as the
user sees it.
Don't use split buttons for action groups with actions that the user isn't perceiving as related.

See also
Page Types and Layouts
Actions in AL
Adding Actions to a Page
How to Promote Actions
Organizing Promoted Actions
Common Promoted Action Groups
Action Bar Improvements
Behavioral Changes for Promoted Actions
Pages with Action Bar Improvements
Promoted Actions
2/6/2023 • 8 minutes to read • Edit Online

You can promote actions that are used more often than others and thereby ensure quick access to them. This
type of actions is called promoted actions. Promoted actions are set up on the Actions, Navigate, or Report
menus in the action bar, but are also configured to display on the Home tab. You can, however, choose to hide
them on the Actions, Navigate, or Report menus and only show them on the Home tab.
Promoted actions can be used on Card, Document, List, ListPlus, and Worksheet pages to provide quick access
to common tasks that appear under the Home tab.

Promoted actions using the actionref syntax


APPLIES TO: Business Central 2022 release wave 2 and later

With Business Central 2022 release wave 2, the way that you promote actions on pages or page extensions has
changed. Promoting actions is defined in a specific section of the code for a page and it contains a reference to
the action. The new syntax provides more visibility in code, because the promoted actions are grouped in a
separate section. And to the end user, the personalization experience is improved, adding options for promoting
actions.
In Business Central the new action bar is enabled when the feature flag Modern Action Bar on the Feature
Management page is set to Enabled. The flag can be switched off to simulate legacy behavior, but the
promoted action code in the base application uses the actionref syntax.

NOTE
The legacy syntax for defining promoted actions is still supported in releases going forward, but it's recommended to
implement the new syntax.

NOTE
Removing the Promoted property on a published action is considered a breaking change. For more information, see
AppSourceCop Error AS0031 and UICop Warning AW0013.

To define promoted actions, you specify an area(Promoted) in the actions section of a page or a page
extension. Inside the area(Promoted) section, you can specify one or more actionref sections. An actionref is
an object type that references an action on the page, and by adding it in the promoted area section it's promoted
in the UI. An actionref can only be defined in the area(Promoted) section. You can either create groups in the
area(Promoted) for the actionref references, or you can add actionref sections directly. An actionref
inherits the properties of the referenced action. For page extensions, you can add to existing groups and you can
add new groups.
For more information about behavioral changes introduced with the new action bar, see Behavioral Changes for
Promoted Actions.
Split buttons for actions
As part of the new programming model for promoted actions, you can combine multiple actions into a split
button to help organize the actions that you're promoting, thereby reducing clutter and improving coherence
and closeness of related actions. A split button can be defined for a page action group, which renders as a
combination of a button and a menu. Use the ShowAs property to specify that a certain page action group
should render as a split button. For more information, see ShowAs Property.
Syntax example
This example illustrates a page with the promoted area syntax. In the example the area(Processing) section
defines the MyBaseAction action for the page, which triggers a Hello world message. The MyBaseAction will be
available from under the Processing group in the action bar and it will be promoted because it's added to the
area(Promoted) section, which defines the actions to promote. The example illustrates that you can group your
actionref sections, or specify them ungrouped. The actionref(MyPromotedActionRef; MyBaseAction) promotes
the defined MyBaseAction so that it, in addition to being placed in the Processing group, also is promoted for
easy access on the page.. Also, the example illustrates using a split button for Group2 where two actionref s

page 50105 ActionRefPage


{
actions
{
area(Promoted)
{
actionref(MyPromotedActionRef; MyBaseAction)
{
}
group(Group1)
{
actionref(MySecondPromotedActionRef; MyBaseAction)
{
}
}

group(Group2)
{
ShowAs = SplitButton;

actionref(MySplitButtonPromotedActionRef; MyBaseAction)
{
}

actionref(MyOtherSplitButtonPromotedActionRef; MyBaseAction)
{
}
}
}
area(Processing)
{
action(MyBaseAction)
{
Visible = true;
trigger OnAction()
begin
Message('Hello world!');
end;
}
}
}
}

Extensibility and compatibility


Switching over to use the new promoted actions syntax can be done gradually as legacy and new syntax will co-
exist for a while. We do, however, encourage you to switch over as soon as you can. As you refactor the code,
there are a couple of things to be aware of in that process:
It's not allowed to use both legacy and new syntax for promoted actions on the same page or page extension.
This means that if you add actionref syntax to your code, the Promoted properties ( Promoted ,
PromotedOnly , PromotedActionCategories , and PromotedCategory ) won't be allowed.
Across a project you can mix legacy and new syntax and:
You can implement the new actionref syntax on a page without breaking any existing page
extensions.
You can write a page extension with the new actionref syntax based on a page that uses the legacy
syntax.
A code action for converting pages using legacy syntax is available with Business Central 2022 release wave 2.
The code action can be applied to a narrow or broader scope of code. For more information, see AL Code
Actions.

Promoting actions by category (legacy syntax)


NOTE
The following section describes the former way of defining promoted actions for Business Central. It's recommended to
switch to the actionref syntax for defining promoted actions.

You can promote any command from the existing actions menus to the ribbon. If there are no promoted actions,
the ribbon remains hidden. To promote an action on the Home tab, you set the Promoted property of the
action. If you want to display the action only on the Home tab, then you add an extra step to set the
PromotedOnly property. For more information, see Promoted Property and PromotedOnly Property.
Promoted actions can be grouped. You can add promoted actions by different grouped categories. Typically,
promoted actions are displayed in the ribbon of a page. You can organize promoted actions into different
categories, where each category is indicated by a caption in the ribbon. You define up to 10 categories for a
page. The following figure illustrates a page that has promoted actions under the following categories.
New Document
Request Approval
Customer

You assign a promoted action to a category by setting the PromotedCategor y property of the action. By
default, these category names correspond to the captions that are displayed for the category on the page in
Dynamics 365 Business Central. You'll typically want to change the captions, especially the Category4 through
Category10 captions. See the table below for the default PromotedCategor y values. To change the default
captions, set the PromotedActionCategories property. You type the values of the
PromotedActionCategories where each caption is separated with a comma as shown below:

PromotedActionCategories =
'New_caption,Process_caption,report_caption,category4_caption,category5_caption,category6_caption,category7_
caption,category8_caption,category9_caption,category10_caption';
The position of the caption in the list determines its corresponding category setting in the PromotedCategor y
property for the actions as described in the table below.

P RO M OT EDA C T IO N C AT EGO RIES DEFA ULT P RO M OT EDC AT EGO RY


C A P T IO N P O SIT IO N VA L UES EXA M P L E

First New New_caption

Second Process Process_caption

Third Report Report_caption

Fourth Category4 Category4_caption

Fifth Category5 Category5_caption

Sixth Category6 Category6_caption

Seventh Category7 Category7_caption

Eighth Category8 Category8_caption

Ninth Category9 Category9_caption

Tenth Category10 Category10_caption

You can change category captions on a page-by-page basis and for each Dynamics 365 Business Central
Windows client language.
For more information about these properties, see PromotedCategory Property and PromotedActionCategories
Property.

Assigning an icon to the promoted actions


Each promoted action has an icon associated with it. You can accept a default icon, or choose your own from the
Dynamics 365 Business Central image library by using the Image property, where each promoted action has an
icon associated with it. Also, you can use a larger icon that makes it more prominent to the user by using the
PromotedIsBig property. For more information, see Image Property and PromotedIsBig Property.
Example
The example shows how to promote actions on a Customers page using different properties:
1. The actions in the example are promoted to display in the New Document , Request Approval and
Customer groups on the Home tab.
2. The Sales Quote and Sales Invoice actions are promoted to the ribbon and grouped in a category called
New Document .
3. The PromotedCategory value; Category5 corresponds the caption position in the PromotedActionCateogories
value with the New Document caption.
4. Each promoted action in the example is assigned to a unique icon. Additionally, to display bigger icons, the
Sales Quote and Contact actions are set with the PromotedIsBig property.
5. The Sales Quote and Send Approval Request actions are set to appear only on the Home tab.

page 50103 Customers


{
PageType = Card;
SourceTable = Customer;
PromotedActionCategories = 'New,Process,Report,Manage,New Document,Request Approval,Customer,Page';

actions
{
area(Creation)
{
action("Sales Quote")
{
Promoted = true;
PromotedCategory = Category5; // PromotedActionCategories = New Document
PromotedOnly = true;
PromotedIsBig = true;
Image = NewSalesQuote;
ApplicationArea = All;
trigger OnAction()
begin
Message('Create sales quote');
end;
}
action("Sales Invoice")
{
Promoted = true;
PromotedCategory = Category5; // PromotedActionCategories = New Document
Image = SalesInvoice;
ApplicationArea = All;
trigger OnAction()
begin
end;
}
}
area(Processing)
{
action("Send Approval Request")
{
Promoted = true;
PromotedOnly = true;
PromotedCategory = Category6; // PromotedActionCategories = Request Approval
Image = SendApprovalRequest;
ApplicationArea = All;
trigger OnAction()
begin
end;
}
action("Cancel Approval Request")
{
Promoted = true;
PromotedCategory = Category6; // PromotedActionCategories = Request Approval
Image = CancelApprovalRequest;
ApplicationArea = All;
trigger OnAction()
begin
end;
}
}
area(Navigation)
{
action(Contact)
{
Promoted = true;
PromotedCategory = Category7; // PromotedActionCategories = Customer
PromotedIsBig = true;
Image = CustomerContact;
ApplicationArea = All;
trigger OnAction()
begin
end;
}
action("Account Details")
{
Promoted = true;
PromotedCategory = Category7; // PromotedActionCategories = Customer
Image = Account;
ApplicationArea = All;
trigger OnAction()
begin
end;
}
}
}
}

For more examples of how to use actions, see Page Object and Page Extension Object.

See Also
Actions Overview
Adding Actions to a Page
Behavioral Changes for Promoted Actions
Actions in AL
Adding Actions to a Page
Actions in the User Interface
How to Promote Actions
Organizing Promoted Actions
Common Promoted Action Groups
Action Bar Improvements
Organizing Promoted Actions
2/6/2023 • 4 minutes to read • Edit Online

The following article gives guidance on which actions you should promote, how to organize the actions, and
where to place the promoted actions.

Which actions should be promoted in a page?


To promote an action in a page, place an actionref for it in the promoted area in the page object. The
recommendation is to only promote actions that are frequently used by the users of the page and actions that
are an expected part of a common action group on the page.
Give prominence via promotion only to actions that you expect many users need for their work and avoid
promoting actions that have little or no tracked usage. When there's only a few users that need a certain action,
it's better to let them personalize that action to a prominent place they prefer rather than promoting the action
for everyone, which will distract the many users who don’t need it.
You can configure and new define user roles (profiles) when you want to coordinate promoted actions across
pages to suit a certain set of users needing a certain set of actions. For more information, see Customizing the
User Interface for User Roles.

Promote actions dependent on page type


For a business entity, for example, a Customer, there's no virtue in promoting the exact same set of actions on
the customer list and the customer card page, even when the same set of actions is available on both pages. On
the contrary, doing so may not align with the patterns of use and it risks cluttering the action bar with actions
that too few users need.
Instead, on list pages, use action promotion to give priority to:
Actions that allow users to process multiple selected rows at a time
Actions that give access to more details about the chosen record
Actions that users find relevant even as they might not see all fields about the record
Actions that users are most likely to use after creating or updating a record using the card page need only be
promoted in the card page, and not in the list. For example, it's more useful to promote the action “Request
Approval” in card and document pages than in list pages, since most users will check or update information in
the card or document before requesting approval of it.

How should promoted actions be organized?


Once you’ve decided on the set of actions to promote in a page, it's time to organize the chosen set into a
proper sequence and grouping. This must be done in a way where users easily discover the actions they need
when they need them.
Before starting to create new groups for actions in a page, consider the total set of promoted actions in the
page. If there are five or fewer promoted actions, it's often preferable to avoid creating new groups, and instead
keep the actions together, and not in separate groups.
NOTE
If a page only has actions promoted to the Process/Home group, then the Business Central web client will show the
actions as if they're not placed in a group. This is known as unpacking of the Home/Process group.

Within each group of actions, choose a sequence of actions that respect their relative importance. Start with
actions that a user is likely to use first, or often, when opening a page. Common action groups are the exception
to this recommendation, as they must instead have a consistent sequence of actions across the pages where
they appear.
Use subgroups within a group when the total number of actions in a group is more than 7.

Guideline for placing promoted actions


T H E P RO M OT ED A C T IO N . . . VA RIAT IO N S REC O M M EN DAT IO N S

Updates or creates data or info A) The action is an expected part of a Promote the action to its expected
(possibly via an intermediate dialog common action group on the page, for common action group. For example,
page) and with clear feedback that the example Post . promote the Post action to the
action took place. common action group named
Examples: Post, Suggest lines, Indent “Posting.”

- B) The action is particular to the page, Action should be promoted to


and not an expected part of a Home/Process.
common action group.

Opens a relevant or related page (not A) The page that opens has Action should be placed in the
a dialog) and that has no apparent information that is specific to the common entity action group, which is
side effects. current record/row in the page. the one bearing the name of the main
Examples: Statistics, Dimensions entity of the page, for example,
Customer.

- B) The page that opens has the same Action should be placed in the
information regardless of current common Navigate action group.
record/row in the page.

Is an action that runs a report, either (no variation) Place report actions in the common
directly or via an intermediate dialog action group Reports.
page (request page).

See also
Actions in AL
Adding Actions to a Page
Actions in the User Interface
How to Promote Actions
Common Promoted Action Groups
Action Bar Improvements
Behavioral Changes for Promoted Actions
Pages with Action Bar Improvements
Common Promoted Action Groups
2/6/2023 • 3 minutes to read • Edit Online

Business Central defines the following common action groups as part of the standard application functionality.
The list isn't exhaustive, but shows the most common action groups, their typical use, and the recommended use
of the split button capability.

C O M M O N A C T IO N GRO UP C H A RA C T ERIST IC S SH O W A S SP L IT B UT TO N

Home, or Process This group has the caption Home in No


entity-oriented pages (Card,
Document, ListPlus) and the caption
Process in collection-oriented pages
(Worksheet and List). In both cases,
the group holds actions that change or
update the current entity/entities. This
group should have actions that start
or end tasks, as the user sees it.

<Name of an entity> The caption of the Entity group in No


For example Customer and Order page matches that of the business
entity represented by the page. For
example, on the Customer Card page,
the entity group has the caption
Customer. Actions in an entity group
let the user access information related
to the entity on display in the page,
and usually has a caption describing
the type of information, for example
Statistics.

Approve Has actions to approve, reject, No


delegate, and view comments.
Used in these page types: Document
(13), List (3)

Entry Appears in lists and worksheets that No


show entries of some sort, often
ledger entries, and has actions for
finding related entries, and for
managing dimensions.
Used in these page types: List (15),
Worksheet (4)

Incoming Document Appears in document pages for actions No


that manage attachments that
represent external documents.
Used in these page types: Document
(12), List (1), Worksheet (2).

Item Availability by Holds the options to view item No


availability by.
Used in these page types: List (3),
Worksheet (6)
C O M M O N A C T IO N GRO UP C H A RA C T ERIST IC S SH O W A S SP L IT B UT TO N

Line Like the entity group, the Line group No


has actions that navigate to
information related to the current line.
The Line group is used instead of an
Entity group when the lines in a list or
worksheet aren't representing an
entity.
Used in these page types: List (8),
Worksheet (38)

Navigate Has actions to open relevant pages No


that aren't related to the current
record or selected line, yet useful to
quickly navigate to when at a given
place.
Used in these page types: Card (8),
Document (6), List (14)

Page Has actions to manage how the page No


displays columns and rows.
Used in these page types: Worksheet
(23)

Posting, or Post/Print Has actions that combine posting or Yes


previewing with printing or other
means of document creation in the
process.
Used in these page types: Document
(17), List (8), Worksheet (23)

Prepare Has actions that prepare the current No


page for further processing. Often, the
actions in the prepare group are
copying or otherwise pulling in data in
preparation for editing, updating, and
posting.
Used in these page types: Document
(20), Worksheet (8)

Print/Send Has actions that print and/or sends No


the current page or a related
document. The destination of the
printing or sending process varies
based on the chosen action.
Used in these page types: Document
(24), List (15)

Release For use with documents that have a Yes


Release/Reopen action pair.
Used in these page types: Document
(20), List (15)

Report or Reports For placement of relevant reports on a No


given page.
Used in these page types: Card (11),
Document (11), List (46)
C O M M O N A C T IO N GRO UP C H A RA C T ERIST IC S SH O W A S SP L IT B UT TO N

Request Approval For actions related to sending an No


approval request and canceling any
outstanding approval requests.
Used in these page types: Card (3),
Document (13), List (3), Worksheet (3).

Show Has actions that manage what No


information appears on a page with a
grid, for example to filter out rows with
certain values.
Used in these page types: List (2),
Worksheet (5).

Synchronize For actions that set up data coupling No


to other systems, and for
synchronizing data based on the
couplings.
Used in these page types: Card (6),
Document (2), List (15).

See also
Actions in AL
Adding Actions to a Page
Actions in the User Interface
How to Promote Actions
Organizing Promoted Actions
Action Bar Improvements
Behavioral Changes for Promoted Actions
Pages with Action Bar Improvements
Action bar improvements
2/6/2023 • 3 minutes to read • Edit Online

With Business Central 2022 release wave 2, we’ve organized the action bar menus to keep related actions
together and avoid the same action being available in multiple menus. This helps reduce clutter and confusion,
especially for users new to Business Central.
The use of a Navigate menu has been reduced, and, where applicable, its contents merged with the entity menu.
The entity menu is the one bearing the name of the entity displayed on a page. Going forward, the Navigate
menu will only hold links to pages that aren't directly related to the current record yet useful to quickly navigate
to when at a given place.
Certain actions have been given a more prominent placement in the action bar. This reduces the number of
selects to reach often-used actions and makes relevant actions more discoverable.
Split buttons are well-known from other Microsoft products as a combination of a button and a menu and are
introduced in Business Central 2022 release wave 2 in certain places. This type of control gives you quick one-
click reach to the first action in a menu via the left button part and access to other related actions via the right
dropdown part.
The ways that users can customize menus to suit their purpose and preference are improved with the new
action bar. That means earlier limitations to which and where actions could be moved no longer apply, which
greatly empowers users in personalizing pages and in configuring profiles.
The improvements listed above are available to current Business Central users as soon as they get the upgrade
to release wave 2, 2022.

Optionally available to all customers upgraded to Business Central,


Wave 2, 2022
In addition to the improvements that are visible to all customers after upgrading to Business Central 2022
release wave 2, the release contains more optimizations of how the action bar supports users in their work.
These extra optimizations are available to all upgraded customers, but not enabled right away with the upgrade.
To activate the optimizations for a customer who upgraded to Business Central 2022 release wave 2, the admin
enables the Modern Action Bar feature in the Feature Management page.
With the Modern Action Bar feature enabled, the following further improvements take effect for all users in a
Business Central environment:
With document, card, worksheet, and listplus pages, the action bar is now presented in the pinned state when
opened for the first time. This helps discovering relevant actions in the action bar and provides one-click reach
to actions, without first pinning the action bar yourself.
With document pages that have a Lines subpage, or any other page having a subpage, the subpage’s actions are
now visible right away, without requiring that you select “More options.”
On document, card, worksheet, and listplus pages, the Process tab is renamed to Home, which better aligns with
the ribbon terminology that users see in other Microsoft products.
On document pages that have Post and Release actions, these are now presented as split buttons in the Home
tab. This provides better discoverability and one-click access to these often-used actions.
On several other pages, certain actions have been grouped into split buttons when the actions are strongly
connected by the effect they have. For example, a new split button is created for the actions Correct , Cancel ,
and Create corrective credit memo. This provides one-click access to Correct, which is the most often used
among the three.

For customers signing up to Business Central after October 1


Customers who sign up and start using Business Central 2022 release wave 2, after October 1 will get the
benefit of all the action bar improvements described here, including those optimizations that are optional for
upgrading customers.
Every customer using Business Central 2022 release wave 2, whether after an upgrade or as a new customer,
can choose to disable the Modern Action Bar feature. This is an option that can be used if an extension
incompatibility is discovered, or if the user interface changes require time to introduce to users.

See also
Actions in AL
Adding Actions to a Page
Actions in the User Interface
How to Promote Actions
Organizing Promoted Actions
Common Promoted Action Groups
Action Bar Improvements
Behavioral Changes for Promoted Actions
Behavioral Changes for Promoted Actions
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 2 and later

With Business Central 2022 release wave 2, we introduce a new syntax for defining promoted actions. The new
syntax groups the promoted actions in a separate section, so that the code is easier to scan. And on the UI, the
new syntax improves the personalization experience, by adding options for promoting actions.

Behavioral changes
N EW B EH AVIO R ( V21) P REVIO US B EH AVIO R ( V20)

During personalization, if you hide a base action, all During personalization, if you clicked "Remove" on a base
actionref s will also be hidden. action, it would disappear, which was equivalent to making
the action set to PromotedOnly = true ; it would only show
up in the promoted section.

If base actions are inside a hidden group, then the Promoted actions had an implicit copy of the Visible
actionref s will be also hidden, even if the base actions property of the base actions, which made them unrelated to
themselves are visible. the parents of the base actions. Due to this behavior, this
was not an issue in v20.
Note: This behavior is maintained when the feature flag
Modern Action Bar on the Feature Management page
is set to Disabled.

Promoted categories are never merged into the Manage If you renamed one of the promoted categories to Manage,
system group anymore. However, if there's a custom group then they were merged into the Manage system group.
called Manage, the merge is done. If there are multiple promoted categories that are renamed
to Manage, then actions inside were all merged into the
Manage system group. This could, for example, happen if
there were multiple extensions that renames different
promoted categories to Manage.

When all actions inside a group has an actionref , then Promoted actions were rendered on the right-hand side
the group is no longer rendered. This condition is applied unless PromotedOnly was set. If every action had
recursively. For example, if every action is promoted, then PromotedOnly = true , then the Actions group would also
there'll be no Actions group visible on the right-hand side. not render.
Note: In a future release actionrefs will be treated by
PromotedOnly by default in the future.

If a hidden group contains actions with dynamic visibility and Actions with dynamic visibility were initially visible. Then, if
the visibility evaluates to true without the parent, then the the parent was hidden and because their visibility was never
actions will be ghosted during design mode even if the modified, they would disappear from the page.
visibility has never been modified.

See also
Promoted Actions
Actions in AL
Adding Actions to a Page
Actions in the User Interface
How to Promote Actions
Organizing Promoted Actions
Common Promoted Action Groups
Action Bar Improvements
Pages with Action Bar Improvements
2/6/2023 • 4 minutes to read • Edit Online

This table provides an overview of all the pages in Business Central that contain the action bar improvements
with 2022 release wave 2 (version 21.0).

PA GE ID PA GE N A M E PA GE T Y P E

4 Payment Terms List

5 Currencies List

7 Customer Price Groups List

11 Shipment methods List

14 Salespersons/Purchasers List

20 General Ledger Entries List

21 Customer Card Card

22 Customer List List

25 Customer Ledger Entries List

26 Vendor Card Card

27 Vendor List List

29 Vendor Ledger Entries List

30 Item Card Card

31 Item List List

36 Assembly BOM List

38 Item Ledger Entries List

39 General Journal Worksheet

40 Item Journal Worksheet

41 Sales Quote Document

42 Sales Order Document

43 Sales Invoice Document


PA GE ID PA GE N A M E PA GE T Y P E

44 Sales Credit Memo Document

49 Purchase Quote Document

50 Purchase Order Document

51 Purchase Invoice Document

52 Purchase Credit Memo Document

76 Resource Card Card

77 Resource List List

88 Job Card Document

92 Job Ledger Entries List

103 Account Schedule Names List

104 Account Schedule Worksheet

113 Budget ListPlus

121 G/L Budget Names List

130 Posted Sales Shipment Document

132 Posted Sales Invoice Document

134 Posted Sales Credit Memo Document

136 Posted Purchase Receipt Document

138 Posted Purchase Invoice Document

142 Posted Sales Shipments List

143 Posted Sales Invoices List

144 Posted Sales Credit Memos List

145 Posted Purchase Receipts List

146 Posted Purchase Invoices List

179 Reverse Entries List

189 Incoming Document Document


PA GE ID PA GE N A M E PA GE T Y P E

190 Incoming Documents List

201 Job Journal Worksheet

232 Apply Customer Entries Worksheet

233 Apply Vendor Entries Worksheet

251 General Journal Batches List

253 Sales Journal Worksheet

254 Purchase Journal Worksheet

255 Cash Receipt Journal Worksheet

256 Payment Journal Worksheet

262 Item Journal Batches List

283 Recurring General Journal Worksheet

291 Req. Worksheet Worksheet

344 Navigate Worksheet

372 Bank Account Ledger Entries List

379 Bank Acc. Reconciliation ListPlus

392 Phys. Inventory Journal Worksheet

393 Item Reclass. Journal Worksheet

408 G/L Balance by Dimension Card

428 Shipping Agents List

434 Reminder Document

436 Reminder List List

490 Acc. Schedule Overview List

498 Reservation Worksheet

507 Blanket Sales Order Document

509 Blanket Purchase Order Document


PA GE ID PA GE N A M E PA GE T Y P E

516 Sales Lines List

518 Purchase Lines List

521 Application Worksheet Worksheet

554 Analysis by Dimensions Card

556 Analysis View List List

573 Detailed Cust. Ledg. Entries List

574 Detailed Vendor Ledg. Entries List

610 IC General Journal Worksheet

615 IC Inbox Transactions Worksheet

623 Unapply Customer Entries Worksheet

624 Unapply Vendor Entries Worksheet

654 Requests to Approve List

658 Approval Entries List

672 Job Queue Entries List

673 Job Queue Entry Card Card

790 G/L Account Categories List

900 Assembly Order Document

902 Assembly Orders List

914 Assemble-to-Order Lines Worksheet

950 Time Sheet Worksheet

951 Time Sheet List List

952 Manager Time Sheet Worksheet

953 Manager Time Sheet List List

954 Manager Time Sheet by Job Worksheet

973 Time Sheet Card Document


PA GE ID PA GE N A M E PA GE T Y P E

981 Payment Registration Worksheet

1007 Job Planning Lines List

1020 Job G/L Journal Worksheet

1173 Document Attachment Details List

1290 Payment Reconciliation Journal Worksheet

1292 Payment Application Worksheet

1294 Pmt. Reconciliation Journals List

1345 Sales Price and Line Discounts List

1500 Workflows List

1801 Assisted Setup List

5050 Contact Card ListPlus

5052 Contact List List

5116 Salespersons/Purchasers Card Card

5123 Opportunity List List

5124 Opportunity Card Card

5335 Integration Table Mapping List List

5400 Item Unit Group List List

5404 Item Unit of Measure List

5406 Prod. Order Line List List

5510 Production Journal Worksheet

5522 Order Planning Worksheet

5601 Fixed Asset List List

5604 FA Ledger Entries List

5628 Fixed Asset G/L Journal Worksheet

5629 Fixed Asset Journal Worksheet


PA GE ID PA GE N A M E PA GE T Y P E

5740 Transfer Order Document

5742 Transfer Orders List

5768 Warehouse Receipt Document

5770 Warehouse Put-away Document

5774 Warehouse Activity List List

5779 Warehouse Pick Document

5785 Warehouse Activity Lines List

5802 Value Entries List

5803 Revaluation Journal Worksheet

5805 Item Charge Assignment (Purch) Worksheet

5875 Physical Inventory Order Document

5900 Service Order Document

5933 Service Invoice Document

5978 Posted Service Invoice Document

6050 Service Contract Document

6510 Item Tracking Lines Worksheet

6520 Item Tracing Worksheet

6630 Sales Return Order Document

6640 Purchase Return Order Document

7016 Sales Price List ListPlus

7315 Warehouse Movement Document

7324 Whse. Item Journal Worksheet

7326 Whse. Phys. Invt. Journal Worksheet

7330 Posted Whse. Receipt Document

7335 Warehouse Shipment Document


PA GE ID PA GE N A M E PA GE T Y P E

7337 Posted Whse. Shipment Document

7341 Whse. Shipment Lines List

7342 Whse. Receipt Lines List

7345 Pick Worksheet Worksheet

7351 Movement Worksheet Worksheet

7365 Whse. Reclassification Journal Worksheet

7375 Inventory Put-away Document

7377 Inventory Pick Document

7382 Inventory Movement Document

8614 Config. Package Card Document

8615 Config. Packages List

8624 Config. Package Fields List

8626 Config. Package Records Worksheet

8632 Config. Worksheet List

9170 Profile Card Card

9300 Sales Quotes List

9301 Sales Invoice List List

9302 Sales Credit Memos List

9305 Sales Order List List

9307 Purchase Order List List

9308 Purchase Invoices List

9620 Page Fields List

9650 Custom Report Layouts List

9652 Report Layout Selection List

9802 Permission Sets List


PA GE ID PA GE N A M E PA GE T Y P E

9807 User Card Card

99000813 Planned Production Order Document

99000818 Prod. Order Components List

99000822 Order Tracking Worksheet

99000823 Output Journal Worksheet

99000829 Firm Planned Prod. Order Document

99000831 Released Production Order Document

99000846 Consumption Journal Worksheet

99000852 Planning Worksheet Worksheet

99000883 Sales Order Planning List

99000886 Subcontracting Worksheet Worksheet

See also
Actions in AL
Adding Actions to a Page
Actions in the User Interface
How to Promote Actions
Common Promoted Action Groups
Action Bar Improvements
Behavioral Changes for Promoted Actions
Designing Profiles
2/6/2023 • 3 minutes to read • Edit Online

A profile is the mechanism that makes a Role Center page and its associated pages and reports available to
users in the client. It enables you to build an individual experience for users based on their role in the company
by customizing the pages that they use to perform the daily tasks. In the client, profiles are referred to as Roles .
When users sign in to Business Central, they are doing so under a specific role. Users can switch the role from
the My Settings page.
Creating profiles in AL involves two different object types: profile object and page customization object.

Profile objects
A profile object specifies an ID for the profile, a display name that appears in the client, a role center page, and
the page customization objects that apply to the profile. Different profiles can use the same Role Center page.

Page customization object


A page customization object specifies layout and action modifications to a specific page object. For example, you
can move actions, fields, columns on list, or entire parts. The modifications apply only to the profile that they are
used with. The page customizations will be seen by all users of the profile.
To make the modifications, you use placement keywords in the layout and actions sections.
The same page customization objects can be used in different profile objects. A profile object does not
necessarily use any page customization objects, but a page customization has no effect without being associated
with a profile object.

Example
The following example creates a profile object that uses the Business Manager role center page. It uses two page
customization objects; one that modifies the Business Manager Role Center page and another that modifies
the Customer List page.
profile TheBoss
{
Description = 'This is the profile for the Boss';
RoleCenter = "Business Manager";
Customizations = MyCustomization1, MyCustomization1;
Caption = 'Boss';
}

pagecustomization Configuration1 customizes "Business Manager Role Center"


{
actions
{
// Hides the Customers action
modify(Customers)
{
Visible = false;
}
}
}

pagecustomization MyCustomization customizes "Customer List"


{
layout
{
{
// Moves the Balance (LCY) column after the Phone No. column
moveafter("Phone No.";"Balance (LCY)")
}
}
}

Using the client to create AL profiles and page customizations


Creating profiles and page customizations can also be done from the client. This will typically be done by
administrators or consultants to create new profiles or fine-tune the page customizations that are provided by
extensions. However, as a developer, you can also leverage the client to make profiles and page customizations
in AL extensions. For more information, see Using the Client to Create Profiles and Page Customizations.

Translating profiles
A profile's Caption and ProfileDescription properties appear in the client user-interface, so you will typically
want to translate these into different languages. Like other objects, this is done by creating XLIFF files for the
different languages from the source language. The generated XLIFF file contains a <source> tag for both the
Caption and ProfileDescription to which you can add a <target> tag for the translated text. For more
information, see Working with Translation Files.
For example, the following code is the content of an XLIFF file for translating the example profile mentioned
above from its source language, en-US, to the target language da-DK.
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en-US" target-language="da-DK" original="profiles">
<body>
<group id="body">
<trans-unit id="Profile 3523819904 - Property 4111922599" size-unit="char" translate="yes"
xml:space="preserve">
<source>The Boss</source>
<target>Chefen</target>
<note from="Developer" annotates="general" priority="2"></note>
<note from="Xliff Generator" annotates="general" priority="3">Profile TheBoss - Property
ProfileDescription</note>
</trans-unit>
<trans-unit id="Profile 3523819904 - Property 2879900210" size-unit="char" translate="yes"
xml:space="preserve">
<source>Boss</source>
<target>Chef</target>
<note from="Developer" annotates="general" priority="2"></note>
<note from="Xliff Generator" annotates="general" priority="3">Profile TheBoss - Property
Caption</note>
</group>
</body>
</file>
</xliff>

See Also
Developing Extensions
AL Development Environment
Page Object
Page Extension Object
Page Extension Properties
Profile Object
2/6/2023 • 2 minutes to read • Edit Online

The profile object in Dynamics 365 Business Central allows you to build an individual experience for each user
profile. The Profile object performs a validation to check whether the specified role center page exists, and page
customization objects exists, when you define a new profile object. On a page customization you can add
changes to the page layout, and actions; but you cannot add variables, procedures, or triggers.

NOTE
Page customizations only apply to the RoleCenter they are specified for. In order to see them, in Dynamics 365 Business
Central under My Settings , Role Center change to the specific RoleCenter that a page customization is defined for.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

NOTE
The property allowDebugging , which is a setting under resourceExposurePolicy does not apply to page
customizations. Page customizations defined in an extension with allowDebugging set to false can still be copied
using Designer. For more information, see Resource Exposure Policy Setting.

Snippet support
Typing the shortcut tprofile will create the basic layout for a profile object when using the AL Language
extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Profile example
The following profile object example creates a profile for the MyRoleCenter Role Center, which is available in the
Role Explorer in the UI and available to end-users. The profile also depends on the customization
MyCustomization and modifies the layout of the Customer List to make the Name field invisible using the
modify method. For more information, see Profile Properties.
profile MyProfile
{
Description = 'Some internal comment that only the Dev can see';
Caption = 'My User-friendly Name';
ProfileDescription = 'A detailed description of who is this profile for, why/how to use it (etc)';
RoleCenter = MyRoleCenter;
Enabled = true;
Promoted = true;
Customizations = MyCustomization;
}

pagecustomization MyCustomization customizes "Customer List"


{
layout
{
modify(Name)
{
Visible = false;
}
}
}

See Also
AL Development Environment
Developing Extensions
Pages Overview
Page Customization Object
Page Customization Object
2/6/2023 • 2 minutes to read • Edit Online

The page customization object in Dynamics 365 Business Central allows you to add changes to the layout and
actions on page that are accessible for a profile. See Using keywords to place actions and controls for how to
place actions and controls on a page customization object.
The page customization object has more restrictions than the page extension object; when you define a new
page customization object, you cannot add variables, procedures, or triggers.

NOTE
A single page customization can be used with multiple profiles within the same extension. Page customizations only apply
to the RoleCenters they are specified for. In order to view or changes the RoleCenters in the client, go to My Settings >
Role Center .

NOTE
Extension objects can have a name with a maximum length of 30 characters.

NOTE
Modifying actions in Cue groups on page extensions is not supported.

NOTE
The property allowDebugging , which is a setting under resourceExposurePolicy does not apply to page
customizations. Page customizations defined in an extension with allowDebugging set to false can still be copied
using Designer. For more information, see Resource Exposure Policy Setting.

Snippet support
Typing the shortcut tpagecust will create the basic layout for a page customization object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Views
Views in Dynamics 365 Business Central are used on list pages to define a different view of the data on a given
page. Views can be defined for Pages, Page Extensions, and Page Customization. For more information, see
Views.
Page customization example
The following page customization example MyCustomization makes changes to Customer List . By using the
moveafter method, Blanket Orders is moved after the Orders action item. And the modify method is used to
hide the NewSalesBlanketOrder action item.

profile TheBoss
{
Description = 'The Boss';
RoleCenter = "Business Manager Role Center";
Customizations = MyCustomization;
Caption = 'Boss';
}

pagecustomization MyCustomization customizes "Customer List"


{
actions
{
moveafter(Orders; "Blanket Orders")

modify(NewSalesBlanketOrder)
{
Visible = false;
}

}
}

You can use the same page customization on another profile within the same extension package by referencing
its name from the profile definition, for example:

profile TheSalesman
{
ProfileDescription = 'The Boss';
RoleCenter = "Sales Manager Role Center";
Customizations = MyCustomization;
Caption = 'Salesman';
}

See Also
Developing Extensions
AL Development Environment
Page Object
Page Extension Object
Views
Page, Page Fields, and Page Extension Properties
Using the Client to Create Profiles and Page
Customizations
2/6/2023 • 5 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

Besides creating profiles and page customizations by writing AL code, you can use the client. The client is a
useful alternative, because you work with the user interface just as the users would. This method is especially
advantageous for consultants, application administrators, and less technical users.

Overview
For detailed instructions on how to use the client to create and modify profiles, see the following articles in the
Business Central application help:
Create Profiles
Customize Pages for Profiles.
A consequence of using the client is that profile changes apply only to the tenant. Extension-based profiles and
customizations, by contrast, are available for all tenants. However, the client lets you export user-created profiles
and page customizations from a tenant, then import them on another tenant.
Profiles created in the client are marked as (user-created) profiles. The export and import functionality lets
you:
Backup profile and page customizations locally.
Make further changes to profiles and page customizations away from the production environment.
Replicate profiles and page customizations on other environments and tenants.
Preview changes in sandbox environments before going into production.

IMPORTANT
You can't use the import functionality to migrate legacy profiles from Dynamics NAV or early versions of Business Central.

Exporting profiles
When you export profiles, the system exports all user-defined profiles and page customizations that have been
made in the tenant. It doesn't export profiles and page customizations introduced by extensions.
To export profiles from the client, open the Profiles (Roles) page, and select the Expor t Profiles action. A zip
file is downloaded to your computer. The file is referred to as a profile package.
Once you have the profile package, you can import it as-is to another tenant. Or, you extract the files and make
more changes to profiles and page customizations. When you're done, you compress the files into a profile
package again and import it on tenants.
NOTE
To export profiles, a user requires read permission to the Profiles page and table as a minimum. This capability allows
normal users to hand over profiles to others for troubleshooting.

Importing profiles
Importing profiles lets you add new profiles and page customizations on a tenant or replace existing ones. To
import profiles, do the following steps:
1. Get the profile package that contains the new or modified profiles.
2. Before you import a package, we recommend that you export the current profiles so you have a copy.
3. Open the Profiles (Roles) page, select the Impor t Profiles action, and follow the instructions to import
the profile package.
You don't have to import all profiles contained in the package. You can select specific profiles.
When you replace a profile, signed-in users of the profile may be interrupted briefly.

IMPORTANT
To import profiles, you must be assigned the SUPER or D365 Profile Mgmt permission set.

Working with the profile package and files


A profile package is a zip file that contains profile and page customizations in separate files. These files basically
contain AL source code. The following table provides an overview of the file types in a profile package.

F IL E T Y P E DESC RIP T IO N

app.json A required configuration file that includes dependencies to


the base application and system application. In most cases,
you shouldn't modify this file after exporting it. The app.json
must be included in the profile package that you import.

profile.json A required configuration file that specifies information about


the profiles in the package. In most cases, you shouldn't
modify this file after exporting it. The profile.json must be
included in the profile package that you import.

profile file An AL file for a user-created profile. There's a separate file for
each profile. A profile file has the format
Profile._<profile ID>_.al .

profile extension file An AL file for customizations made to an extension-based


profile. These file types have the format
ProfileExtension._<profile ID>_.al .

page customization file An AL file that specifies all customizations made to a page
for a specific profile. A page customization file has the format
PageCustomization._[page name]_.Configuration\
<number\>.al
.
The sections that follow explain a bit more about the file types and creating the profile package.
Profile files
Each user-created profile is exported to a separate AL file. This file contains the profile object that defines the
profile's ID, name, and Role Center. It also includes references to the page customizations it uses. For example,
let's say you created a profile with the ID MyProfile that uses the role center page 9022 Business Manager
Role Center . You then customized the Business Manager Role Center itself and the Customer list page. The
exported profile package would contain a file called PROFILE.MyProfile.al . This file would include the
following code:

profile MyProfile
{
CaptionML = ENU='My Profile';
Enabled = true;
ProfileDescriptionML = ENU='This is my sample profiles';
Promoted = true;
RoleCenter = 9022;
Customizations = Configuration1; Configuration2;
}

The Customizations property identifies the page customization objects used by the profile.
Profile extension files
Customizations made to extension-based profiles are exported to a profile extension file. This file includes a
profileextension object that specifies two types of information, depending on the changes:

Properties that specify metadata like, the CaptionML, ProfileDescriptionML, and RoleCenter.
References to configuration files that define page customizations.
For example, let's say you changed the description and customized the Customer page for the Business
Manager profile that is provided by the Base Application extension. The profile package would then contain the
file ProfileExtension._BUSINESS MANAGER.al . This file will contain code similar to the following code:

profileextension BUSINESSMANAGER_1 extends "BUSINESS MANAGER"


{
CaptionML = ENU='Business Manager';
Enabled = true;
ProfileDescriptionML = ENU='My changed functionality for managers in charge of keeping the business viable
by determining product and company direction.';
Promoted = false;
RoleCenter = 9022;
Customizations = Configuration3;
}

Configuration3 is a reference to a page customization file for the Customer page. For more information, see
the next section.
Page customization files
Page customizations made to user-created profiles and extension-based profiles are exported to AL files that
include a pagecustomization object. This object defines each modification to the page. Referring to the examples
above, the zip file would include three files:
PageCustomization.Business Manager Role Center .Configuration1.al
PageCustomization.Customer List .Configuration2.al
PageCustomization.Customer List .Configuration3.al
The files would include code similar to the following code:
P a g e C u st o m i z a t i o n . B u s i n e s s M a n a g e r R o l e Ce n te r.C o n fi g u r a t i o n 1 .a l

pagecustomization Configuration1 customizes "Business Manager Role Center"


{
layout
{
modify(Control16)
{
Visible = false;
}
}
actions
{
}
}

P a g e C u st o m i z a t i o n . Cu s to m e r L i s t.C o n fi g u r a t i o n 2 .a l

pagecustomization Configuration2 customizes "Customer List"


{
layout
{
modify("Balance (LCY)")
{
Visible = false;
}
}
actions
{
}
}

P a g e C u st o m i z a t i o n . Cu s to m e r L i s t.C o n fi g u r a t i o n 3 .a l

pagecustomization Configuration3 customizes "Customer List"


{
layout
{
modify("Balance Due (LCY)")
{
Visible = false;
}
}
actions
{
}
}

Creating a profile package for import


After you make modifications to exported profiles and page customizations, you'll have to create the profile
package before you can import the changes.
The profile package doesn't have to contain the same files that were originally exported. But it must contain the
app.json and profile.json files. Otherwise, you can't import the package. To create the profile package, just
compress the files into a zip folder.

See Also
Developing Extensions
AL Development Environment
Page Object
Page Extension Object
Page Extension Properties
Control Add-in Style Guide
2/6/2023 • 5 minutes to read • Edit Online

This article offers a variety of stylistic definitions that are used throughout Dynamics 365, which you can apply
to your control add-ins to create an experience that complements Dynamics 365.

Introduction
Control add-ins for Dynamics 365 extend a business solution by surfacing contextual functionality alongside
business data. Control add-ins empower users to get more done without costly context switching, no matter
which device they access Dynamics 365 from. Typical uses of control add-ins include unique data visualizations,
surfacing controls from a third party service, or displaying related content from another data source.
Apart from the functionality, an important aspect of creating a control add-in is making sure the control add-in
looks good and blends seamlessly into Dynamics 365. To achieve this, you should follow these basic principles:
Apply similar patterns for command, navigation and presentation of data.
Favor content over chrome
Design for all platforms and input methods.
Make it accessible to all users.
Make it enjoyable and keep users in control.
Dynamics 365 uses a set of specific colors and fonts. You can employ these colors and fonts in your control add-
ins to give it a style that matches the rest of client's user interface.

Colors
Choosing the right color gives the interface visual continuity. Color can be used to convey information to users,
indicate interactivity, give feedback, and more. The following sections describe the colors used in Dynamics 365.
The colors can be used on all aspects of a UI element, such background, border, text, and more.
Main colors
The following colors represent the Dynamics 365 theme main palette.

C O LO R NAME USE H EX VA L UE

Primary color Prominent UI elements and #00B7C3


areas.

Secondary color UI elements and areas in #505C6D


default or subdued state.

Style colors
The following colors are used to express or accent conditions or user activity in the UI. For example, these colors
are used as sentiments, or color indication, on Cues.
C O LO R DESC RIP T IO N H EX VA L UE

Standard #212121

Accent #00B7C3

Strong #212121

Favorable #35AB22

Ambiguous #9F9700

Unfavorable #EB6965

Attention #EB6965

Subordinate #A7ADB6

More palette colors


The following table includes additional colors that you can use in the UI.

C O LO R DESC RIP T IO N H EX VA L UE

Yellow #C9C472

Green #88CE81
C O LO R DESC RIP T IO N H EX VA L UE

Red #E97768

Blue #75B5E7

Light green #59CCB4

Sky 75D8E7

Egg EEEA86

Orange #E89E63

Violet #DBBDEB

Teal #39B294

Grass #73BA5A

Scarlet #E65E6D

Chart colors
The following table describes the colors used in charts.
C O LO R DESC RIP T IO N H EX VA L UE

- #505C6D

- #008089

Primary color #00B7C3

Yellow #C9C472

Red #E97768

Blue #75B5E7

Light green #59CCB4

Sky 75D8E7

Egg EEEA86

Violet #DBBDEB

Teal #39B294

Grass #73BA5A
Applying colors
To apply a color scheme to the control add-in, you specify CSS rule-sets that use the following properties:

P RO P ERT Y DESC RIP T IO N

color Specifies font color.

background-color Specifies background colors.

border-color Specifies Border colors.

For example, to change the background of a part of your UI to use the Secondary (#505C6D) color, write the
following CSS:

.my-ui-part {
background-color: #505C6D;
}

If you want to change the text color of a caption to the Primary (#00B7C3) color, use the following CSS:

.my-caption {
color: #00B7C3;
}

Typography
The main goal of typography is to provide clean and readable text in the user interface. Similar to colors,
typography can also be used to convey or communicate conditions to the user.
Font Families
Dynamics 365 uses the following font families to specify the typeface and weight for text elements, such as
headings, captions, messages, and so on:

EXA M P L E NAME VA L UE

Segoe UI "Segoe UI", "Segoe WP", Segoe,


device-segoe, Tahoma, Helvetica,
Arial, sans-serif

Segoe UI Light "Segoe UI Light", "Segoe WP


Light", device-segoe-light,
"Segoe WP Semilight", "Segoe
UI", "Segoe WP", Segoe, Tahoma,
Helvetica, Arial, sans-serif

Segoe UI Semilight "Segoe UI Semilight", "Segoe WP


Semilight", device-segoe-
semilight, "Segoe UI", "Segoe
WP", Segoe, Tahoma, Helvetica,
Arial, sans-serif

Segoe UI Semibold "Segoe UI Semibold", "Segoe WP


Semibold", device-segoe-
semibold, "Segoe UI", "Segoe
WP", Segoe, Tahoma, Helvetica,
Arial, sans-serif
Sizes
Dynamics 365 uses the following font sizes for text. The same font family on different clients may apply different
sizes.

EXA M P L E NAME VA L UE

largest-plus-font-size 37.5pt

largest-font-size 30pt

large-plus-font-size 22.5pt

large-font-size 18pt

medium-plus-font-size 15pt

medium-font-size 13.5pt

small-plus-font-size 12pt

small-font-size 10.5pt

smallest-font-size 9pt

Applying Font Families and Sizes


To apply fonts and sizes to text elements in the UI, you need specify the following CSS properties:
Font family. use property font-family .
Font size. use property font-size .
For example, to change a UI element for the Web client to use the font family Segoe UI Light and the size Small
(10.5pt), write the following CSS:
.my-ui-part {
font-family: "Segoe UI Light", "Segoe WP Light", device-segoe-light, "Segoe WP Semilight", "Segoe UI",
"Segoe WP", Segoe, Tahoma, Helvetica, Arial, sans-serif;
font-size: 10.5pt;
}

IMPORTANT
To ensure that the correct fonts are used on devices, do not omit fonts or change the order of the fonts.

Example
This examples illustrates how to use CSS to style a simple HTML UI part of a control add-in. The example
includes three UI controls, as shown in the following HTML code:

<div class="addin">
<div class="control">
<div class="caption">Name:</div>
<div class="value">
<input type="text" name="name">
</div>
</div>

<div class="control">
<div class="caption">Surname:</div>
<div class="value">
<input type="text" name="name">
</div>
</div>

<div class="control">
<div class="submit">Submit</div>
</div>
</div>

The following is CSS code for styling the controls, including padding, background colors, and fonts:
.addin {
padding: 1em;
background-color: #505C6D; /* Sets the background color to "Secondary" */
}

.addin .control {
border-color: #00B7C3; /* Sets the border color to "Primary" */
}

.addin .control .caption {


color: #00B7C3; /* Sets the captions to "Primary" */

/* Segoe UI Light, small */


font-family: "Segoe UI Light", "Segoe WP Light", device-segoe-light, "Segoe WP Semilight", "Segoe UI",
"Segoe WP", Segoe, Tahoma, Helvetica, Arial, sans-serif; /* Sets the font of the caption to ""Segoe UI
Light" */
font-size: 10.5pt;
}

.addin .control .value {


color: #008089; /* Tertiary shade 2 */

/* Segoe UI, medium */


font-family: "Segoe UI", "Segoe WP", Segoe, device-segoe, Tahoma, Helvetica, Arial, sans-serif;
font-size: 12pt;
}

.addin .control .submit {


color: white; /* Sets the caption text to "white" */
background-color: #00B7C3; /* Sets the background to "Primary */

/* Segoe UI Semibold, medium */


font-family: "Segoe UI Semibold", "Segoe WP Semibold", device-segoe-semibold, "Segoe UI", "Segoe WP",
Segoe, Tahoma, Helvetica, Arial, sans-serif;
font-size: 12pt;
text-transform: uppercase; /* Sets the caption to use all uppercase letters */
}

See Also
Control Add-in Best Practices
Introducing the Dynamics 365 Business Central
Mobile App
2/6/2023 • 3 minutes to read • Edit Online

The app displaying the Business Central tablet client and Business Central phone client is targeted at users in
small and medium sized businesses that want to access data from a tablet or a phone. The main advantages of
this offering are portability and flexibility, which allows end users to perform tasks when they are away from
their desk. Having a Dynamics 365 Business Central solution that runs on a smaller device also brings it in the
hands of many more users and your app is easy to distribute.

IMPORTANT
The Business Central tablet client and Business Central phone client do not replace the Business Central Web client.
Instead, they offer a touch interface for a limited set of application scenarios compared to the Business Central Web client.

The Business Central Web client supports more complex business processes and heavier data entry than it is
possible on the Business Central tablet client and Business Central phone client. Business Central is also
designed for intensive use, and the user can have multiple windows open at the same time, but this is neither
possible in Business Central phone client or Business Central tablet client. For more information, see Differences
and Limitations When Developing Pages for the Business Central Mobile App.
The design for the Business Central tablet client is optimized for the touch experience and reduced use of the
on-screen keyboard. On the other hand, the design for the Business Central phone client is about touch
optimization, given its smaller screen size. The Business Central phone client layout is designed to support one-
hand and both hands use, which allows the important data and buttons to be available within thumbs reach.

NOTE
In this documentation, you will see mentions of Business Central tablet client, Business Central phone client, and
Dynamics 365 Business Central Mobile App. Business Central tablet client and Business Central phone client describe the
interface tailored to the category of mobile device, which is one of the tools available for developers for designing mobile
solutions, whereas Dynamics 365 Business Central Mobile App is the common name for the app across all devices; the
end result made with these tools.

Considering the user scenarios


When you design your solution for the Business Central tablet client and the Business Central phone client, you
must make sure that scenarios are simple enough to be meaningful and usable. The tablet and phone designs
are meant for lighter tasks and are useful, for example, for traveling salespeople or service technicians who need
a portable, online, easy-to-use app that provides an overview, for example, of daily tasks and items in stock.
Depending on the scenarios that your tablet and phone solution will support, it will either make sense to create
a new Role Center for tablet and phone only, or share the same Role Center across all of the client types. In some
cases, it can make sense to have a user sign in with two different profiles, one for a desktop client and one for
mobile devices. In other cases, duplicating pages and designing specific duplicates to be device-oriented is the
best solution.
If you have existing page objects that you want to make available on Business Central tablet client or Business
Central phone client, we strongly recommend that you plan time to evaluate carefully which actions, sections,
and fields will be needed for the user scenarios you want to enable. Fields and actions that are not needed
should not be visible to users of your app. The UI must be simplified significantly to work well on a small device.
For more information, see Designing for Different Screen Sizes on Tablet and Phone.

Supported credential types


Business Central tablet client and Business Central phone client support the same credential types as Business
Central Web client. For more information, see Authentication and Credential Types.

See Also
Getting Started Developing for the Dynamics 365 Business Central Mobile App
Differences and Limitations When Developing Pages for the Dynamics 365 Business Central Mobile App
Deciding on Your Tablet and Phone Strategy
2/6/2023 • 3 minutes to read • Edit Online

To offer users a great mobile experience, you must decide on a strategy for how to accomplish this based on an
analysis of your users' needs. This topic explains the different options for developing for the Business Central
tablet client and Business Central phone client, but the documentation you will find in this section is primarily
focused on the first of these scenarios.

Mobile app development strategy


This section briefly describes some of the options that exist for Dynamics 365 Business Central.

F O R M O RE IN F O RM AT IO N ,
DEVELO P M EN T ST RAT EGY W H AT A L SO TO C O N SIDER EXA M P L ES SEE

Business Central Dynamics 365 Business - For salespeople tracking Introducing the Dynamics
platform Central only supports a customers, looking up item 365 Business Central
Use the AL Language specific number of page details, and capturing Mobile App
development environment types, and this can be a orders.
to modify and extend the limitation in some type of Getting Started Developing
Business Central tablet development projects. - For technicians on the for the Dynamics 365
client and Business Central road using and re-ordering Business Central Mobile
phone client.This scenario spare parts. App
resembles developing for
Business Central Web client. - For simple approval
The main advantages of this scenarios.
strategy are:

- Extending and modifying


Business Central tablet and
phone clients is useful for a
minimal learning curve and
a reduction of development
costs; scenarios
automatically work on
multiple operating systems
without having to worry
about the maintenance.

- You can reuse existing


investments in Dynamics
365 Business Central page
objects, business logic, and
javascript-based client add-
ins. Ideal for user scenarios
which can be achieved by
using simple application
pages.
F O R M O RE IN F O RM AT IO N ,
DEVELO P M EN T ST RAT EGY W H AT A L SO TO C O N SIDER EXA M P L ES SEE

Power App The standard Business For field salesforce in need Connecting to Your
Use the Power Apps Central connector for Power of user experience that is Business Central Data to
platform connected to Apps only supports built in more customized or tightly Build a Business App Using
Business Central either APIs, so you may need to connected to 3rd party Power Apps
using the Business Central use custom connector software or hardware.
connector in Power Apps or feature to access your Create a canvas app from a
custom connector and custom APIs. template in Power Apps
access your modify data.

Connected mobile app Cost to learn development A simple touch interface for OData Web Services Data
Based on OData web tools and languages outside users to scan their access Modification
services or SOAP web AL, preparing new card for time registration.
services technologies, write development environments. OData Web Services
an app that interacts with
Dynamics 365 Business Cost of licensing any of SOAP Web Services
Central. Visual Studio these tools, and having to
includes project templates maintain code for different Web Services
for this kind of app. operating systems.

This strategy applies when


you want to build a highly
customized app with your
own UI design that takes
advantage of all the rich
features which native apps
provide.

Remarks
If you are developing using the AL language, use a browser for continuous development and test of the Business
Central tablet client and the Business Central phone client solution that you are working on. Switching to
running in a browser is an easy and efficient way to test what new and modified pages look like. Running the
Business Central tablet client and Business Central phone client in a browser is only recommended for
development scenarios. For more information, see Opening the Dynamics 365 Business Central Tablet or Phone
Client from a Browser.

See Also
Getting Started Developing for the Dynamics 365 Business Central Mobile App
Introducing the Business Central Mobile App
Getting Started Developing for the Dynamics 365
Business Central Mobile App
2/6/2023 • 2 minutes to read • Edit Online

The Business Central tablet client and Business Central phone client are built on the same framework as the
Business Central Web client, such that they are all based on the same Dynamics 365 Business Central pages.
Developing for Business Central tablet client and Business Central phone client is not much different from
developing pages for Business Central Web client either, since it is also done from the AL Language
development environment.

Steps for Developing for the Business Central tablet client and
Business Central phone client
The first step to take when you are developing for the Business Central tablet client and Business Central phone
client is to consider the design and implementation of the solution:
What is the business scenario that you want to support?
Do you want to extend your existing data model?
Should the solution work well on both a desktop computer, on the tablet and also on a phone?
What design should the Role Center that will be the central dashboard for the solution have?
Understanding the business scenario is important to build the best solution. Design your solution for users who
are most typically occasional users who need an overview of their daily work status and perform relatively
simple or light data entry. Many of these preparations resemble those for developing for Business Central Web
client, but in an even smaller scale.
Once the data model, users, permissions, and profiles are in place, you can start developing the Role Center. You
can either reuse an existing Role Center or create a new one. This will depend on the business scenario. The
Business Central tablet client and the Business Central phone client are designed to be smart about laying out
the same Role Center depending on the display target.
When developing for the Business Central phone client you want to think even more about design and usability
on a very small screen. On the phone the app will always by default start a page in view mode, meaning that the
user actively must switch to edit mode.
There are some best practices and limitations to consider in particular caused by the smaller screen size and
touch experience. For more information, see Differences and Limitations When Developing Pages for the
Dynamics 365 Business Central Mobile App. On devices that run the Business Central Mobile App and have a
camera and location capability you also have a couple of additional options. For more information, see
Implementing the Camera in AL and Implementing Location in AL.
To complete designing your Business Central Mobile App solution, you should consider offering users Help, to
guide them through pages or workflows. For more information about adding help to your solution, see Extend
and Collaborate on the Help for Dynamics 365 Business Central.
The next steps are to consider how to deploy your solution and how to distribute it to your customers. After you
have completed your solution, you can send an e-mail to the users to let them know that they can download
Dynamics 365 Business Central from the relevant store and include the organization URL and sign-in
information. For more information, see Linking to the Dynamics 365 Business Central Mobile App.
See Also
Deciding on Your Tablet and Phone Strategy
Differences and Limitations When Developing Pages for the Dynamics 365 Business Central Mobile App
Designing for Different Screen Sizes on Tablet and
Phone
2/6/2023 • 2 minutes to read • Edit Online

When designing application pages for the Business Central tablet client and the Business Central phone client, it
is best practice to consider the size of the tablets or phones that your end users have access to. It is an
advantage if the solution works well on both small and large screen sizes, but we also recommend that you
consider thoroughly the most frequently used screen sizes for your end user experience.
Designing for small screens can be more challenging, because pages will show fewer fields, columns, and tiles.
Therefore, a good way to identify issues on how your application pages are displayed is to test on the smallest
supported screen size.

Form factor considerations


Users can scroll both the navigation and the content area of the Business Central Mobile App on a tablet to
access all data for a given page. However, it is recommended that the scrolling in the navigation bar is minimal.
The navigation bar is the area on the left-hand side of Business Central Mobile App and it is designed to provide
easy access to important information and tasks that the user should not lose sight of when scrolling on the
content area.
On phones the Business Central Mobile App displays only one part at a time on the Role Center. On the Home
page, the Activity tiles are always displayed first, and you navigate through the bottom menu to explore the
content area.
Guidance for page element types on smallest tablet devices
The following table provides a list of elements that fit in the page content or the app bar without scrolling.

PA GE T Y P E DISP L AY S O N SM A L L EST TA B L ET DEVIC E

RoleCenter 4 tiles in 1 group, or 2 groups together with 2 tiles

List Pages 5 columns of type Text50 or 8 columns of type Text20


PA GE T Y P E DISP L AY S O N SM A L L EST TA B L ET DEVIC E

Card Pages - CardPage Factbox with up to 15 fields


- 2 CardPage Factboxes with up to 6 fields each
- Activities Factboxes with 4 tiles in 1 group, or 2 groups
together with 2 tiles

Document Pages - CardPage Factbox with up to 15 fields


- 2 CardPage Factboxes with up to 6 fields each
- Activities Factboxes with 4 tiles in 1 group, or 2 groups
together with 2 tiles

Testing using a browser


Using a browser you can test how your application pages will look on various device sizes. For more
information, see Opening the Business Central Tablet or Phone Client from a Browser.
When running Business Central tablet client or Business Central phone client in a browser, you can use Microsoft
Edge Developer Tools to emulate different screen sizes. For more information, see Microsoft Edge Developer
Tools.

See Also
Deciding on Your Tablet and Phone Strategy
Differences and Limitations When Developing Pages for the Dynamics 365 Business Central Mobile App
Displaying Data as Tiles
Gesture Property
Differences and Limitations When Developing
Pages for the Business Central Mobile App
2/6/2023 • 4 minutes to read • Edit Online

Developing for the Business Central tablet client and Business Central phone client is similar to developing for
the Business Central Web client. However, there some natural limitations on tablets and phones, such as not
having a physical keyboard and mouse, as well as a smaller screen.

Differences and limitations overview


The following table describes some of the most common differences and limitations that you might experience
when developing for Business Central tablet client and Business Central phone client.

REC O M M EN DAT IO N /
C O N C EP T O N TA B L ET ON PH ONE EXA M P L E REM A RK S

Activity groups Only the Home Only the Home Home and Posted Design pages to
activity group is activity group is Documents on the expose the workflows
shown. shown. Sales Order needed by the user.
Processor For example,
Role Center. configure the profile
to show the
important list pages
under the Home
activity group.
Alternatively,
consider designing a
new Role Center if
the activities for the
activity group greatly
vary from activities in
other activity group.

Selecting multiple Not available. Not available. Ctrl+A or Avoid scenarios


records in lists Ctrl+Click on requiring selecting
rows in a list using multiple rows on a
Business Central Web list. Also, try to
client. minimize actions on
lists.

Actions in the action Only Promoted Only Promoted On the Use the development
bar actions are shown. actions are shown. Small Business environment to
Role Center. promote actions.
Alternatively,
configure the profile
and add actions to
the Home tab.

FactBoxes Not shown on List Not shown on List Customer list on Make sure the same
pages or Worksheet pages or Worksheet the information is visible
pages. pages. Small Business on the corresponding
Role Center. card page of the
given record.
REC O M M EN DAT IO N /
C O N C EP T O N TA B L ET ON PH ONE EXA M P L E REM A RK S

Advanced filters No column-specific No column-specific On the Customer Send data to Excel


filtering is available. filtering is available. list page. and do the complex
filtering there.

Tell Me Not available yet. Not available yet. On Business Central Design pages to
Web client. expose the workflows
needed by the user.
For example via list
places, tiles or
actions.

Role Explorer Not available yet. Not available yet. On Business Central Design pages to
Web client. expose the workflows
needed by the user.
For example via list
places, tiles or
actions.

Fields in FastTabs Fields in FastTabs on Not available. Design List pages to


list pages are not avoid having
shown. Only the important columns
repeater control is on the far right of
shown in the content the column list.
area of the page. Assume you have no
control over how
many columns are
displayed and
consider that only
the first few columns
will be made visible.

Select from full list Not available on Not available on On the Item Card Make sure the
lookups. Users are lookups. Users are when selecting the appropriate columns
not able to run not able to run Base Units of are visible on the
actions on a lookup actions on a lookup Measure . lookup. The user is
page, and they page, and they still able to filter,
cannot access the full cannot access the full scroll, and search
set of records. set of records. through the lookup.

Search across list Partly supported. Partly supported. On the Customer


columns Search will not Search will not list page.
include FlowFields. include FlowFields.

Lookups Available. Available, with the See examples on the


difference that Customer Card
advanced and simple page.
lookups behave
similarly on the
phone. The lookup
will not bring up the
card, show FactBoxes,
or any field groups.

Matrix controls Not available. Not available. See example in


G/L Budget .
REC O M M EN DAT IO N /
C O N C EP T O N TA B L ET ON PH ONE EXA M P L E REM A RK S

File download Available. Cannot Available. Cannot Trial Balance


download multiple download multiple report in the Print
files at the same files at the same to Excel check box.
time. time.

Worksheet pages Available. Not available; an Sales Price Run this type of page
error message is Worksheet or from the Business
displayed. Cash Flow Central Web client, or
Worksheet. Business Central
tablet client.

Lists Available. Available, with the Customers or Sales


difference that these Orders pages.
are displayed in a
brick layout with a
number of
differences and
limitations. For an
overview, see
Displaying Data as
Tiles.

Indentation in Available. Not available. The Chart of Accounts


repeater controls repeater control will and Contacts List
be rendered as a pages.
regular flat brick
layout.

Scope of actions Available. Available, but there


are some behavioral
differences regarding
the Scope Property.
Also, see Defining
Action Scope for
Business Central
Pages.

Automatic input Not available. Not available. Customer Card The reason for this
focus on first editable page. behavior is to
field of a page prevent the in-app
In the Web client, keyboard from
focus will initially displaying
automatically be on and occupying screen
the first editable field space.
(such as the Name
field), enabling you to
change the value
right away.

In the Tablet or
Phone client, this
field will not be in
focus; instead, you
will have to manually
select the field first in
order to make
changes.
See Also
Displaying Data as Tiles
Implementing the Camera in AL
Implementing the Location in AL
Role Center Behaviors
Defining Action Scope for Business Central Pages
Opening the Business Central Tablet or Phone
Client from a Browser
2/6/2023 • 2 minutes to read • Edit Online

You can open the Business Central tablet client or the Business Central phone client by using a browser from a
device that has a network connection. This can make it easier to test your solution during the design phase.

IMPORTANT
The steps in this article illustrates how you can open the Business Central tablet client in a browser. The syntax and
options for opening Business Central phone client in a browser are the same; just replace tablet with phone in the
examples later in this section.

To open Business Central tablet client in a browser


1. Open the web browser.
2. In the address box of the browser, type one of the following URLs.

TO O P EN URL EXA M P L E

The Role Center for the default https://ComputerName:Port/WebSe https://MyBCWeb:8080/BC210/tabl


company rverInstance/tablet et

Or (for multitenant deployments)

https://ComputerName:Port/WebSe
rverInstance/tablet?
tenant=TenantID

The Role Center for a specific https://ComputerName:Port/WebSe https://MyBCWeb:8080/BC210/tabl


company rverInstance/tablet? et?
company=CompanyName company=CRONUS%20Internationa
l%20Ltd.
Or

https://ComputerName:Port/WebSe
rverInstance/tablet?
tenant=TenantID&company=Comp
anyName

A specific page https://ComputerName:Port/WebSe https://MyBCWeb:8080/BC210/tabl


rverInstance/tablet?page=ID et?page=22

Or

https://ComputerName:Port/WebSe
rverInstance/tablet?
tenant=TenantID&page=ID
TO O P EN URL EXA M P L E

A specific report https://ComputerName:Port/WebSe https://MyBCWeb:8080/BC210/tabl


rverInstance/tablet?report=ID et?report=8

Or

https://ComputerName:Port/WebSe
rverInstance/tablet?
tenant=TenantID&report=ID

A specific profile https://ComputerName:Port/WebSe https://MyBCWeb:8080/BC210/tabl


rverInstance/tablet?profile=ProfileID et?profile=Small-Business

Or

https://ComputerName:Port/WebSe
rverInstance/tablet?
tenant=TenantID&profile=ProfileID

Substitute the following parameters:


ComputerName with the name of the computer that is running the Business Central Web Server
components.
Por t with the port number that you configured for the Business Central Web Server components
during installation.
WebSer verInstance with the virtual directory alias under which the Business Central tablet client
or the Business Central phone client exists on the web server. For more information, see Installing
Business Central Using Setup.
TenantID with the name of the tenant that you want to connect to. This parameter is only required
when Business Central is deployed in a multitenant architecture. The tenant that you specify must
be mounted on the Business Central Server instance that the Business Central Web client connects
to. For more information, see Multitenant Deployment Architecture.
CompanyName with the name of the company in Business Central. This parameter is optional
and is only needed if you want to open a different company than the one specified in My
Settings .
ID with the ID that is assigned to the page or report in Business Central.
ProfileID with the ID that is assigned to the profile in Business Central.

See Also
Introducing the Dynamics 365 Business Central Mobile App
Develop a Sales Rep Role Center for the Tablet
Client
2/6/2023 • 3 minutes to read • Edit Online

In this example, you will learn how to create a new Role Center for the Business Central tablet client. Developing
for the Business Central tablet client occurs in the AL Language development environment and is not much
different from developing for one of the other Business Central clients. This example will concentrate on how to
build a Role Center for a sales representative, which links to already existing page objects, but combined in a
way so that it works well on the tablet.

About this example


This example illustrates the following tasks:
Creating a Role Center page
Adding existing pages to the Role Center
Adding actions to pages from the Role Center
Testing the Role Center page

Prerequisites
To complete this example, you will need:
Business Central installed with a developer license
Business Central Web Server components
CRONUS International Ltd. demonstration database
A supported browser. For more information, see System Requirements for Dynamics 365 Business Central
2020 Release Wave 1

Story
Simon is a partner developer working for CRONUS International Ltd. Nancy is a Sales Representative at Contoso
Consulting. Simon has to build a new Role Center to support Nancy in her job. When at work, Nancy spends
part of her time on the road with only her tablet available on customer visits. Nancy needs access to KPIs on the
front page. She needs easy access to filter for the customers who she will visit. When at the customer site, she
creates sales quotes. Simon wants to build a Role Center that can be used on a tablet and he wants to reuse as
much code and as many page objects as possible.
The following code illustrates how Simon implements the Role Center.
page 50106 "Sales Rep Role Center"
{
PageType = RoleCenter;

layout
{
// Add already existing pages to help Nancy access activities, customers, and charts to the Role
Center.
area(RoleCenter)
{
part("O365 Activities"; "O365 Activities")
{
}

part("My Customers"; "My Customers")


{
}

part("Generic Chart"; "Generic Chart")


{
}

part("Trial Balance"; "Trial Balance")


{
}
}
}

// Add actions that link to other pages, which Nancy uses in her daily work on the tablet.
actions
{
area(Creation)
{
action("Sales Quote")
{
Caption = 'New';
RunObject = Page "Sales Quote";
Image = Quote;
Promoted = true;
}

action("Customer List")
{
Caption = 'Customers';
RunObject = Page "Customer List";
Promoted = true;
// Sales Quote as an action item available from the action pane in the New group
PromotedCategory = New;
}

action("Item List")
{
Caption = 'Items';
RunObject = Page "Item List";
Promoted = true;
PromotedCategory = New;
}
}
}
}

For more information about the specifics of Role Center structure and design, see Designing Role Centers.
Simon now wants to test the Sales Rep Role Center that he created, and for testing purposes he uses a browser
window. He enters a URL that specifically opens the page 50006 from tablet.aspx. His URL now resembles this:
https://MyBCWeb:8080/BC210/tablet.aspx?page=50006. For more information, see Opening the Business
Central Tablet or Phone Client from a Browser.

Next steps
Nancy now has a Role Center that gives her access to most of the information that she needs when she is on the
road. The next step for Simon is to refine the Sales Rep Role Center by adding more functionality, for example,
the ability to retrieve more lists or making sure that Nancy can smoothly continue to work when she is back at
the office on her desktop computer.

See Also
Designing for Different Screen Sizes on Tablet and Phone
Differences and Limitations When Developing Pages for the Business Central Mobile App
Designing Role Centers
Role Center Behaviors
Entitlements and Permission Sets Overview
2/6/2023 • 5 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

Business Central uses two main concepts for defining access to functionality: Entitlements and permissions.
Entitlements describe which objects in Business Central a customer is entitled to use according to the
license that they purchased from Microsoft or according to the Azure Active Directory role that they have
assigned in Microsoft 365 Admin Center, such as Global Administrator. Entitlements are only used in the
online version of Business Central.
Permissions describe which objects an administrator or a partner has given the user.
Permission sets combine objects permissions in logical groups (or sets), which can then be assigned to
the users explicitly or through a user group.
For more information about assigning licenses, see Licensing in Dynamics 365 Business Central. For more
information about how to create and assign permissions, see Assign Permissions to Users and Groups.

Permission Set scope


A Business Central solution contains a number of predefined permission sets that are added by Microsoft or by
your software provider (by an ISV application that you installed from AppSource).
Permission sets included with Microsoft and AppSource apps defined as AL objects are of the type System .
End-users cannot create or edit these types of permission sets or the permissions within them. However, they
can copy these permission sets to define their own permission sets and permissions. Permission sets that users
create, from new or as copies, are of the type User-Defined and they can be edited.

Creating entitlements and permission sets in AL


When developing an app, entitlements and permission sets are handled as objects in AL, and existing
permission sets can be extended in AL. The following object types are used for handling entitlements and
permissions:
Entitlement Object
PermissionSet
PermissionSetExtension

NOTE
In the current version of Dynamics 365 Business Central entitlements can only be included with Microsoft apps (enforced
by the AppSource cop rules and the technical validation checks that we run for the apps submitted to AppSource). These
objects will become available for the ISV apps when we introduce ability to monetize AppSource apps in one of our future
releases.

Upgrade considerations
Starting with Business Central 2021 release wave 1 (v18.0), the Business Central demo database, which is
shipped with our on-premises installation, doesn't contain any data in the Permission Set and Permission
tables in the application database. Instead, the System permission sets and permissions are provided as AL
objects of type PermissionSet and PermissionSetExtension , included with Microsoft apps.
The application database tables that used to store the entitlements won't contain any data either, because
entitlements are now defined as AL objects.
Business Central server configuration file (CustomSettings.config) includes a setting that allows on-premises
administrators to decide whether they want to continue using the permissions defined as data or as AL objects:

<add key="UsePermissionSetsFromExtensions" value="true" />

The default value for this setting is true , meaning that the server will be retrieving all System permission sets
and permissions from the AL objects of type PermissionSet and PermissionSetExtension . With the value for this
setting set to true , the permissions data, in case it is still present in the application database, will be
disregarded.
It's not possible to customize the System permission sets and permissions used in the online version of
Business Central. End-users can only copy these types to new permission sets, which they can then adjust to
their needs. For more information, see Assign Permissions to Users and Group.
In the on-premises version of Business Central, even though it's not recommended, the partners can customize
the permission sets and permissions shipped in the application database. In this case, as for any upgrade before,
the changes in Microsoft permissions should be merged with the customized permissions by partners during
upgrade.
Although starting with Business Central 2021 release wave 1 (v.18.0), System permissions are no longer
shipped as data in the application database, the partners can use the same procedure as before to export the
new permissions that are defined using AL objects. The new permission sets and permissions can be exported
into XML file by running XMLport 9171 Import/Export Permission Sets, making it possible to compare and
merge the customized permission sets in your old database with the newly shipped permission sets. Find more
details, see Export and Import Permission Sets and Permissions.
How to upgrade permission sets
When upgrading to version 18, first decide whether you want to use the permissions defined as data or switch
to permissions defined as AL objects. Then, follow the guidelines at Upgrading Permission Sets for details on
how to do the upgrade.

Earlier versions of Business Central


In releases of Business Central prior to 2021 release wave 1 (v18.0), System and Extension permissions and
entitlements were defined as data in the application database:
Entitlements tables:
Entitlement
Entitlement Set
Membership Entitlement
Permissions tables:
Permission Set
Permission
Keeping such sensitive information as data comes with additional maintenance, security, and audit risks for the
software providers (ISVs). Changes applied to this data should ideally be well traceable, easy to update and
maintain. Starting with Business Central 2021 release wave 1, the System permissions and entitlements are
defined in code, using Entitlement, PermissionSet, and PermissionSetExtension AL objects. This change provides
ISVs with all of the advantages of using the AL Language extension in Visual Studio Code and source control
systems (as Visual Studio Online and GitHub) to design, get an overview, and track changes to the objects that
describe user access.
Turning this data into code has another significant advantage: the ability to apply hotfixes to the entitlements
and permissions in the same way that the hotfixes are applied to the apps themselves, simply by updating an
app to a new version which carries fixed code. This improves Business Central support agility considerably,
ultimately improving customer satisfaction with the service.
And finally, the new AL objects are envisioned to become the core building blocks in the story of monetizing the
AppSource apps. It's through these new AL objects that AppSource ISVs will be able to define which capabilities
of their apps should be made available to their users, when the customers purchase their app licenses. With
Business Central 2021 release wave 1, we're paving the way by moving the entitlements and permission sets
into AL objects for Microsoft apps, so that ISVs can follow the same approach for their apps, when the
monetization story is introduced with one of the next releases of Business Central.
User-Defined permission sets and permissions, and functionality around them, remain unchanged. They're still
stored as data in the tenant database:
Tenant Permission
Tenant Permission Set
Permission sets and permissions included with apps in XML format will continue to work as before, however, we
recommend you to start using the AL objects of type PermissionSet and PermissionSetExtension instead.

See Also
Get Started with AL
Entitlement Object
PermissionSet Object
PermissionSet Extension Object
Composing Permission Sets
2/6/2023 • 4 minutes to read • Edit Online

Permissions define a specific level of access to data and objects in the application, like read, insert, modify, and
delete permission on table data. Permission sets combine these permissions in logical groups that can then be
assigned to users. Permission sets in AL are created using the permissionset object, and existing permission sets
are extended using the permissionset extension object. In the client, administrators can't modify these AL-based
permission sets, but they can copy them and modify the copies (see Assign Permissions to Users and Groups).

Design concepts
There are different approaches to creating permission sets.
Fundamental permission sets
One approach is to create a kind of self-contained permission set that includes all the permissions you want to
grant to specific data and objects. These permissions are defined explicitly in the Permissions property of the
permission set or permission set extension object. This approach creates a structure considered to be flat
structure.

The disadvantage with this approach by itself is that if you have to change a permission, like C and D in the
figure, you have to make the change in every permission set that uses the permission.
Composite permission sets
Another approach is to use the IncludedPermissionSets property and ExludedPermissionSets property to create
permission sets that are composed of the other permission sets. Any changes made to the included or excluded
permission sets are automatically propagated to the permission sets that use them. In this manner, you create
permission sets that have hierarchical structure, as illustrated in the following figure. Looking at the figure,
permission set 5 is composed from all permission sets, minus the permissions in permission set 3.
Composite permission sets are easier to maintain and keep up-to-date compared to fundamental permission
sets—especially when building off Microsoft permission sets. This approach enables you to create concise,
reusable permission sets that control access to specific features, which act as building blocks for expanding
other permission sets.
Bringing approaches together
Ultimately, you'll use a combination of these approaches to meet your permission requirements. Many of the
default permission sets from Microsoft follow this approach. The following figure illustrates how different
permission sets (in this case, standard Dynamics 365 permission sets) can be used to compose two custom
permission sets (EMPLOYEE and HR). The permission sets have been simplified for illustration purposes.
Include permission sets
You use the IncludedPermissionSets property to create a permission set that includes permissions from other
permission sets. The property is available on permission set and permission set extension objects.
The following code example illustrates a permission set Sales Person that includes permissions that grant
access, at various levels, to data in different tables. The Assignable property is set to true , which allows the
permission set to be assigned to a user. The Permissions property is set to the list of objects to give permissions
to. The RIMD access assigned to data in the Customer table provides full access, whereas, for example, access is
limited for data in the Currency table only allowing full read and modify permission.

permissionset 50134 "Sales Person"


{
Assignable = true;
Caption = 'Sales Person';

Permissions =
tabledata Customer = RIMD,
tabledata "Payment Terms" = RMD,
tabledata Currency = RM,
tabledata "Sales Header" = RIM,
tabledata "Sales Line" = RIMD;
}

With the IncludedPermissionSets property, you can specify that the permission set Sales Person is also
included in MyPermissionSet .
permissionset50135MyPermissionSet
{
Assignable = true;
Caption = 'My PermissionSet';
IncludedPermissionSets= "Sales Person";

Permissions=
tabledataVendor=RIm,
codeunit SomeCode =x,
codeunit AccSchedManagement=X;
}

The resultant permissions for the MyPermissionSet permission set are then:

tabledata Customer = RIMD,


tabledata "Payment Terms" = RMD,
tabledata Currency = RM,
tabledata "Sales Header" = RIM,
tabledata "Sales Line" = RIMD;
tabledataVendor=RIm,
codeunit SomeCode =x,
codeunit AccSchedManagement=X;

Exclude permission sets


With the ExludedPermissionSets property, you can remove permissions that are defined in other permission sets
from your permission set. The ExcludePermissionSets property isn't supported on permission set extension
objects.
The following code example illustrates how to use the ExcludePermissionSets property.

permissionset50136MyPermissionSet2
{
Assignable = true;
Caption = 'My PermissionSet 2';
IncludedPermissionSets= "MyPermissionSet";
ExcludedPermissionSets = "Sales Person";

Permissions=
tabledataMyTable =RIMD,
}

The resultant permissions defined by the MyPermissionSet2 permission set are then:

tabledataMyTable = RIMD,
tabledataVendor=RIm,
codeunit SomeCode =x,
codeunit AccSchedManagement=X;

Rules, guidelines, and tips


This section explains points that can help you get the resultant permissions that you want.
Permissions are determined by working up the hierarchy, adding or removing permissions at each level.
Exclude permissions take precedence over included permissions when applied on the same level. If an
excluded permission set and included permission set define the same permissions, the excluded permission
set permissions will be used, overriding the included permission set permissions.
Direct permissions will override indirect permissions.
The following table shows how the permissions are determined on a single object when included and excluded
permission sets are used:

P ERM ISSIO N SET A P ERM ISSIO N SET B RESULT

Permissions = tabledata Customer = Permissions = tabledata Customer = tabledata Customer = RIMD


RI iMD
IncludedPermissionSets = B

Permissions = tabledata Customer = Permissions = tabledata Customer = tabledata Customer = RIMD


Ri IMD
IncludedPermissionSets = B

Permissions = tabledata Customer = Permissions = tabledata Customer = tabledata Customer = RI


RIMD iMD
ExcludedPermissionSets = B

Permissions = tabledata Customer = Permissions = tabledata Customer = tabledata Customer = R


RiMD IMD
ExcludedPermissionSets = B

TIP
When including and excluding multiple permission sets, it can be difficult to get an overview of what the resultant
permissions will be. To help, use the View all permissions action from the the permission set in the client.

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Extension Object
Permissions on Database Objects
Assignable Property
IncludedPermissionSets
Permissions Property
Permission Set Object
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

The permission set object in Business Central describes permissions on objects. Permission sets are building
blocks used to compose assignable permission sets and entitlements. Assignable permission sets are
permissions that an admin can assign to users in Business Central, using the Permission Sets page. An
entitlement is a collection of permission sets that constitute a set of meaningful permissions for a user.
Some permission sets can be non-assignable, meaning that they aren't discoverable and assignable in the UI in
Business Central, instead they can be used as building blocks to compose functional assignable permission sets.
For information about which permissions can be assigned to objects, see Permissions on Database Objects.

Designing with cautiousness


If a permission set is extended through AL, the extension will make additive changes to the permission set. This
behavior means an extension can provide elevated privileges to an otherwise limited set of permissions.
Building permission sets that can be extended must be done carefully with this behavior in mind.

Snippet support
Typing the shortcut tpermissionset will create the basic layout for a permission set object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Generate permission set for an object


APPLIES TO: Business Central 2022 release wave 2 and later

When adding new AL objects, it's easy to forget to update the permissions. With the
al.generatePermissionSetForExtensionObjects command, you can generate or update a permission file for the
active project in Visual Studio Code. Choose to create a new permission file or select an existing file to make
updates to. For more information, see AL Language Extension Configuration.

Permission set example


The following example illustrates a permission set Sales Person with permissions given to data in tables, each
with different level of access. The Assignable property is set to true , which allows the permission set to be
assigned to a user. The Permissions property is set to the list of objects to give permissions to. The RIMD access
assigned to data in the Customer table provides full access, whereas, for example, access is limited for data in
the Currency table only allowing full read and modify permission.
NOTE
The name of the permissionset object is limited to 20 characters when the Assignable property is set to true .
Otherwise, it's limited to 30 characters. Exceeding the limit will throw the diagnostic Compiler Error AL0305.

permissionset 50134 "Sales Person"


{
Assignable = true;
Caption = 'Sales Person';

Permissions =
tabledata Customer = RIMD,
tabledata "Payment Terms" = RMD,
tabledata Currency = RM,
tabledata "Sales Header" = RIM,
tabledata "Sales Line" = RIMD;
}

The following example of a permission set illustrates assigned permissions to run codeunits. With the
IncludedPermissionSets property, we specify that the permission set Sales Person is also included in
MyPermissionSet .

permissionset50135MyPermissionSet
{
Assignable = true;
Caption = 'My PermissionSet';
IncludedPermissionSets= "Sales Person";

Permissions=
tabledataVendor=RIm,
codeunit SomeCode =x,
codeunit AccSchedManagement=X;
}

You can also use the ExludedPermissionSets property to exclude permissions defined in other permission sets.
To learn more, see Composing Permission Sets From Other Permission Sets.

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Extension Object
Permissions on Database Objects
Assignable Property
IncludedPermissionSets
Permissions Property
Permission Set Extension Object
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

The permission set extension object in Business Central adds permissions to an existing permission set defined
in AL. A permission set extension object cannot remove permissions from an existing permission set, it can only
add permissions. If you, for example, add an extension to Business Central, you can use permission set extension
objects to grant permissions to the objects in your extension. This means that the admin of Business Central
does not have to assign additional permission sets to the users, because that automatically happens when the
extension is installed, and the permissions go away if the extension is uninstalled.
For information about which permissions can be assigned to objects, see Permissions on Database Objects.

Designing with cautiousness


If a permission set is extended through AL, that extension will make additive changes to the permission set. This
means that an extension can provide elevated privileges to an otherwise limited set of permissions. Building
permission sets that can be extended must be done carefully with this in mind.

Snippet support
Typing the shortcut tpermissionsetextension will create the basic layout for a permission set extension object
when using the AL Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Permission set example


The following permission set extension example extends the Sales Person permission set by adding direct
insert and delete permissions to the Currency table data.

permissionsetextension 50140 "Extended Sales Doc" extends "Sales Person"


{
Permissions = tabledata Currency = ID;
}

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Object
Permissions on Database Objects
Assignable Property
Permissions Property
Permissions on Database Objects
2/6/2023 • 2 minutes to read • Edit Online

This section provides an overview of permissions on objects in Dynamics 365 Business Central.

Permissions
If you have been granted permission to read a page, then you can open the page and view the data that it
displays. If, however, you do not have write permission, you are not allowed to enter data into this page.
Sometimes, when you open a page it displays information from several tables. To access this page, you must
have permission to view all the data displayed by the page. You might not have permission to read directly from
all the tables that the page uses. In this case, you must have indirect permission to read from the tables in
question. Having indirect permission to a table means that you cannot open the table and read from it but can
only view the data it contains indirectly through another object, such as a page or report, that you have direct
permission to access.
Dynamics 365 Business Central has a number of standard predefined security permission sets. You can use
these permission sets as defined or you can change a permission sets to suit your particular needs. You can also
create your own permission sets and assign them the permissions that you want.
Permissions on Objects
The following table describes the permissions that can be assigned for specific objects. When assigning
permissions by using the object types PermissionSet Object and PermissionSet Extension Object these
permissions have been shortened. The table illustrates the abbreviations used.
Permissions on tabledata are specified with the following abbreviations:

P ERM ISSIO N DESC RIP T IO N A B B REVIAT IO N IN A L

Read You can read data. R for direct read access, r for
indirect read access.

Insert You can insert data. I for direct insert permission, i for
indirect insert permission.

Modify You can modify data. M for direct modify permission, m


for indirect modify permission.

Delete You can delete data. D for direct delete permission, d for
indirect delete permission.

Permissions on all objects are specified with the following abbreviations:

P ERM ISSIO N DESC RIP T IO N A B B REVIAT IO N IN A L

Execute You can run this object. X for direct execute permissions, x
for indirect execute permissions.

Wildcard
The wildcard can be used as a shortcut to assign multiple permissions at a time, such as:
Permissions = codeunit * = X;

IMPORTANT
The wildcard must be used with caution, because when it is used in a permission set it grants the permission to all objects
of that type across all permissions. If a permission set with a wildcard is included in an entitlement, it only covers the
objects of that type in the current extension.

Example
All of the permissions illustrated above can be combined into a group of permissions for any given object. For
example:

...
Permissions =
tabledata Customer = RIMD, // Full access
tabledata "Payment Terms" = RMD, // Full read, modify, and delete access - no insert
tabledata Currency = rimd, // Full indirect access
tabledata "Sales Header" = RIM, // full read, insert, and modify access - no delete
tabledata "Sales Line" = RIMD, // Full access
report "Sales Statistics" = X; // Full access
...

See Also
Get Started with AL
Entitlements and Permission Set Overview
Permission Set Object
Permissions on Database Objects
Inherent Permissions
2/6/2023 • 2 minutes to read • Edit Online

With inherent permissions, developers can now grant permissions to a method or event while code executes. As
soon as the code execution is completed, permissions are revoked. Inherent permissions simplify the overall
management and maintenance work of permission sets. With it, a specific AL method or event can get the
elevated permissions necessary to finish the task at hand without getting permission errors. And it helps tighten
overall security by limiting long-term user permissions and giving permissions to the code process instead.
Let’s say a salesperson wants to make a report that includes certain critical pieces of information. In the
background, a method will run a query to fetch the information from the table holding classified data. With
inherent permissions, instead of managing permissions for that salesperson, a developer can add the
permission permanently into the specific code path. This method will be granted permissions for the given
object, which in this case is a table. Now, whenever an authorized person runs this method, the needed
permissions are in place to complete the request.

NOTE
For now, the InherentPermissions attribute is available for Business Central on-premises only. It'll be added to Business
Central online in a later version.

TIP
It's better to use the inherent permissions for small dedicated procedures or system tasks that don't risk data exposure to
users.

Syntax
[InherentPermissions(PermissionObjectType: PermissionObjectType, ObjectId: Integer, Permissions: Text [,
InherentPermissionsScope: InherentPermissionsScope])]

To learn more about the syntax of the InherentPermissions attribute, see InherentPermissions Attribute.

Example
Let's look at a code example for the InherentPermissions attribute.

[InherentPermissions(PermissionObjectType::TableData, Database::Customer, 'r',


InherentPermissionsScope::Both)]

Procedure GetCustomersLocation(): CustomerLocation

Referring to the example explained above, let's say the report needs to show which location has more sales for
the quarter. As it's not ideal to grant access to all data belonging to customers, read permission is granted to the
method instead. It will only fetch the customer's location and leave other details (such as name, address, and so
on) private.
Inherent Entitlements
The inherent permissions and inherent entitlements together, grant more flexibility to the developers that they
can assign permissions to their methods, events, and objects. Developers can define inherent entitlements for
their objects like codeunit, table, page, and so on. In this way, the developers equip all users to have enough
access that they can carry out essential tasks without any halt. And regardless of what access their present
license or entitlement grant them. To learn more about inherent entitlements, see InherentEntitlements Property.

NOTE
Specifying InherentPermissionsScope is optional and the default is Both that includes permissions and entitlements. To
read about different types of scope, see InherentPermissionsScope Option.

See also
Entitlements and Permission Sets Overview
Permission Set Object
Exporting Permission Sets to XML
2/6/2023 • 2 minutes to read • Edit Online

Permission sets that exist in Dynamics 365 Business Central can be exported and packaged for your extension
directly from the client, instead of defining XML by hand. These permission sets are also known as tenant
permissions, and are shown in the UI as Extension permissions. The underlying functionality of permissions
has changed with the latest version of Dynamics 365 Business Central.

IMPORTANT
With the latest version of Dynamics 365 Business Central permissions are no longer defined as data in the application
database. Permissions that can be created by using AL objects are called system permissions. For more information, see
Entitlements and Permission Sets Overview.

To export permission sets from Dynamics 365 Business Central


1. In Dynamics 365 Business Central, search for Permission Sets , and then choose the relevant link.
2. On the Permission Sets page, choose the permissions that you want to export, and then choose Expor t
Selected Permissions .
3. In the Expor t Permission Sets dialog, choose to export permission sets only for the application, only for
the tenant, or for both.
4. Save the file to your extension folder.
5. Delete the permission sets from Dynamics 365 Business Central.
You can generate a permission set file which contains permissions to all the files in your extension. This will
make it easier to start setting up permissions for your app. You can do this by simply creating an extension with
some objects as described below.

To export permission sets using Visual Studio Code


1. In Visual Studio Code, open your extension with objects; pages, reports, tables, queries, codeunits, and/or
XMLports.
2. Open the command palette using the Ctrl+Shift+P keys and select the AL: Generate permission set
containing current extension objects command.

NOTE
If you do this repeatedly, Visual Studio Code will probe for overwriting the file, there is no support for merging
manual corrections into newly generated content.

3. Publish the app.


Now, you have the XML file with default permissions to all your objects.
Example from Visual Studio Code
The following example illustrates the generated .xml file from MyProject which contains a table with objectID
50106 and two object types are generated; <ObjectType>0</ObjectType> is TableData and
<ObjectType>1</ObjectType> is Table .
NOTE
The maximum length of the RoleID attribute is 20 characters. If the RoleID exceeds this length, then the XML schema
validation fails and the corresponding permission set file is not included in the resulting app package. You will get a
warning in the Visual Studio output panel.

<?xml version="1.0" encoding="utf-8"?>


<PermissionSets>
<PermissionSet RoleID="MyProject" RoleName="MyProject">
<Permission>
<ObjectID>50106</ObjectID>
<ObjectType>0</ObjectType>
<ReadPermission>1</ReadPermission>
<InsertPermission>1</InsertPermission>
<ModifyPermission>1</ModifyPermission>
<DeletePermission>1</DeletePermission>
<ExecutePermission>0</ExecutePermission>
<SecurityFilter />
</Permission>
<Permission>
<ObjectID>50106</ObjectID>
<ObjectType>1</ObjectType>
<ReadPermission>0</ReadPermission>
<InsertPermission>0</InsertPermission>
<ModifyPermission>0</ModifyPermission>
<DeletePermission>0</DeletePermission>
<ExecutePermission>1</ExecutePermission>
<SecurityFilter />
</Permission>
</PermissionSet>
</PermissionSets>

Object type mapping


The mapping of object types in the XML such as <ObjectType>0</ObjectType> generated from Visual Studio Code
is the following:

O B JEC T T Y P E N UM B ER

TableData 0

Table 1

Report 3

Codeunit 5

XMLPort 6

Page 8

Query 9

FieldNumber 11

PageExtension 14
O B JEC T T Y P E N UM B ER

TableExtension 15

Enum 16

EnumExtension 17

Profile 18

ProfileExtension 19

See Also
Entitlements and Permission Sets Overview
Permissions on Database Objects
Permissions Property
TestPermissions Property
Events in AL
2/6/2023 • 3 minutes to read • Edit Online

The use of events is a proven and established programming concept that can ease application upgrade and limit
or even eliminate the need for code modifications in customized applications because of application platform
changes.
You can use events to design the application to react to specific actions or behavior that occur. Events enable you
to separate customized functionality from the application business logic. By using events in the application
where customizations are typically made, you can lower the cost of code modifications and upgrades to the
original application.
Code modifications to customized functionality can be made without having to modify the original
application.
Changes to the original application code can be made with minimal impact on the customizations.
Events can be used for different purposes, such as generating notifications when certain behavior occurs or the
state of an entity changes, distributing information, and integrating with external systems and applications. For
example, in the CRONUS International Ltd. demonstration database, events are used extensively for workflow
and Dynamics 365 for Sales integration.
The following table describes all the different event types:

EVEN T T Y P ES DESC RIP T IO N

BusinessEvent Specifies the method to be business type event publisher.

IntegrationEvent Specifies the method to be integration type event publisher.

InternalEvent Specifies the method to be an internal event publisher.

Global Global events are predefined system events.

Trigger Trigger events are published by the runtime.

The process for implementing these events is slightly different. To learn about the different types, see Event
Types.

How events work


The basic principle is that you program events in the application to run customized behavior when they occur.
Events in AL are modeled after Microsoft .NET Framework. There are three major participants involved in events:
the event, a publisher, and a subscriber.
An event is the declaration of the occurrence or change in the application. An event is declared by an AL
method, which is referred to as an event publisher function. An event publisher method is comprised of a
signature only and does not execute any code.
A publisher is the object that contains the event publisher method that declares the event. The publisher
exposes an event in the application to subscribers, essentially providing subscribers with a hook-up point
in the application.
Publishing an event does not actually do anything in the application apart from making the event
available for subscription. The event must be raised for subscribers to respond. An event is raised by
adding logic to the application that calls into the publisher to invoke the event (the event publisher
method).
Partners or subsystems can then take advantage of the published event in their solutions. An ISV that
delivers vertical solutions, and Microsoft itself, are the typical providers of published events.
Business and integration type events must be explicitly published and raised, which means that you must
create event publisher functions and add them to objects manually. On the other hand, trigger events,
which occur on table and page operations, are published and raised implicitly by the system at runtime.
Therefore, no coding is required to publish them.
A subscriber listens for and handles a published event. A subscriber is an AL method that subscribes to a
specific event publisher method and includes the logic for handling the event. When an event is raised,
the subscriber method is called and its code is run. A subscriber enables partners to hook into the core
application functionality without having to do traditional code modifications. Any Dynamics 365 solution
provider, which also includes Microsoft, can use event subscribers.
There can by multiple subscribers to a single event publisher method. However, a publisher has no knowledge of
subscribers, if any. Subscribers can reside in different parts of the application than publishers.

How to implement events


Implementing events consists of the following tasks:
1. Publish the event.
For business and integration events, create and configure a method in an application object to be an
event publisher method. For more information, see Publishing Events. This is not required for trigger
events because these are automatically published by the system.
2. Raise the event.
Add code that calls the event publisher method. For more information, see Raising Events. This is not
required for trigger events because these are raised automatically by the system.
3. Subscribe to the event.
At the consumer end, add one or more subscriber methods that subscribe to published events when they
are raised. For more information, see Subscribing to Events.

See Also
Publishing Events
Raising Events
Subscribing to Events
Isolated Events
Developing Extensions Using the New Development Environment
Event Types
2/6/2023 • 8 minutes to read • Edit Online

Dynamics 365 Business Central supports different types of events for different purposes.

Business events
A business event is a custom event that is raised by AL code. It defines a formal contract that carries an implicit
promise not to change in future releases. It is the expectation that business events are published by solution
ISVs, including Microsoft.
Business events can be compared with publicly released APIs on which 3rd party solution providers develop
integrations and additions. Therefore, the downstream cost of making changes to a business event
implementation can be considerable for those who use the event in their applications. There may be some cases
where changes are required; however, you should keep these to an absolute minimum.
Development considerations
A typical business event reflects changes in “state” with regards to a process. This makes them very well suited
for workflow. An example of a business event could be when a sales order has been posted. It is important to
note that business events should not be tied to the implementation-details, such as the tables or fields in which
the data is stored. Preferably, the event publisher developer should be free to change the implementation, while
still keeping the business event intact. To learn about the syntax and example on how to use the BusinessEvent
type, see BusinessEvent Attribute.
Business events should be documented with the solution, including the before-state and after-state of the
events.

Integration events
An integration event is also a custom event that is raised by AL code, like a business event, except that it does
not carry the same promise of not changing, nor does it have the restriction not to expose implementation
details.
The main purpose of integration events is to enable the integration of other solutions with Dynamics 365
Business Central without having to perform traditional code modifications.
Development considerations
An integration event can be changed to a business event later. At which time, it must adhere to the same implied
contract and commitment as any business event. It can also simply be designed-in hook points for external add-
ons. To learn about the syntax and example on how to use the IntegrationEvent type, see IntegrationEvent
Attribute.
Development considerations
To learn about the syntax and example on how to use the InternalEvent type, see InternalEvent Attribute.

Global events
Global events are predefined system events that are automatically raised by various base application codeunits.
For example, codeunit 40 LoginManagement includes several global method triggers, such as CompanyOpen,
CompanyClose, and GetSystemIndicator. For most of these global method triggers, there are one or two global
events: a before and after event. For example, there is an OnBeforeCompanyOpen event and an
OnAfterCompanyOpen event. The global events are defined as integration event publishers by local methods in
the following codeunits.

C O DEUN IT ID C O DEUN IT N A M E EVEN T

9170 Conf./Personalization Mgt. OnRoleCenterOpen

OnAfterLogInEnd

OnBeforeLogInStart

OnBeforeCompanyOpen

OnAfterCompanyOpen

OnBeforeCompanyClose

OnAfterCompanyClose

42 TextManagement OnBeforeMakeTextFilter

OnAfterMakeDateTimeFilter

OnAfterMakeDateFilter

OnAfterMakeTextFilter

OnAfterMakeTimeFilter

42* Caption Class OnAfterCaptionClassResolve

OnResolveCaptionClass

44 ReportManagement OnAfterGetPrinterName

OnAfterDocumentPrintReady

OnAfterGetPaperTrayForReport

OnAfterGetPrinterName

OnAfterHasCustomLayout

OnAfterDocumentReady

OnAfterDocumentDownload

OnAfterSetupPrinters

OnCustomDocumentMergerex

OnAfterSubstituteReport
C O DEUN IT ID C O DEUN IT N A M E EVEN T

45 AutoFormatManagement OnAfterAutoFormatTranslate

49 GlobalTriggerManagement OnAfterGetGlobalTableTriggerMask

OnAfterOnGlobalInsert

OnAfterOnGlobalModify

OnAfterOnGlobalDelete

OnAfterOnGlobalRename

OnAfterGetDatabaseTableTriggerSetup

OnAfterOnDatabaseInsert

OnAfterOnDatabaseModify

OnAfterOnDatabaseDelete

OnAfterOnDatabaseRename

OnBeforeOnDatabaseInsert

OnBeforeOnDatabaseModify

OnBeforeOnDatabaseDelete

OnBeforeOnDatabaseRename

* Codunit 42 Caption Class was introduced as a replacement for codeunit 42 CaptionManagement . In


previous versions, codeunit 42 CaptionManagement included the OnAfterCaptionClassTranslate event. For
more information, see Breaking Changes in the ALAppExtensions GitHub repo.

Trigger events
Unlike business and integration events which must be programmed, trigger events are predefined events.
Trigger events are published by the runtime and they cannot be raised programmatically. There are two types of
trigger events: database trigger events and page trigger events.

NOTE
Trigger events do not appear as methods in AL for a table or page object.

Database trigger events


Trigger events are automatically raised by the system when it performs database operations on a table object,
such as deleting, inserting, modifying, and renaming a record, as defined in a table. Trigger events are closely
associated with the table triggers for database operations: OnDelete, OnInsert, OnModify, OnRename, and
OnValidate (for fields). For each database operation, there is a "before" and "after" trigger event with a fixed
signature.
Available Database Trigger Events
The following table describes the available database trigger events:

DATA B A SE T RIGGER EVEN T SIGN AT URE DESC RIP T IO N

OnAfterDeleteEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed after a record is deleted from


Database::<Table Name>, a table.
'OnAfterDeleteEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; RunTrigger:
Boolean)

OnAfterInsertEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed after a record is inserted in a


Database::<Table Name>, table.
'OnAfterInsertEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; RunTrigger:
Boolean)

OnAfterModifyEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed after a record is modified in a


Database::<Table Name>, table.
'OnAfterModifyEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
RunTrigger: Boolean)

OnAfterRenameEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed after a record is renamed in a


Database::<Table Name>, table.
'OnAfterRenameEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
RunTrigger: Boolean)

OnAfterValidateEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed after a field is validated when


Database::<Table Name>, its value has been changed.
'OnAfterValidateEvent', '<Field
Name>', <SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
CurrFieldNo: Integer)

OnBeforeDeleteEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed before a record is deleted


Database::<Table Name>, from a table.
'OnBeforeDeleteEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; RunTrigger: Boolean)

OnBeforeInsertEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed before a record is inserted in


Database::<Table Name>, a table.
'OnBeforeInsertEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; RunTrigger: Boolean)
DATA B A SE T RIGGER EVEN T SIGN AT URE DESC RIP T IO N

OnBeforeModifyEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed before a record is modified in


Database::<Table Name>, a table.
'OnBeforeModifyEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
RunTrigger: Boolean)

OnBeforeRenameEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed before a record is renamed in


Database::<Table Name>, a table.
'OnBeforeRenameEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
RunTrigger: Boolean)

OnBeforeValidateEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed before a field is validated


Database::<Table Name>, when its value has been changed.
'OnBeforeValidateEvent', '<Field
Name>', <SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
CurrFieldNo: Integer)

The following table describes the parameters of the trigger events:

PA RA M ET ER TYPE DESC RIP T IO N

Rec Record The table that raises the event.

xRec Record The table that raises the event.

RunTrigger Boolean Specifies whether to execute the code


in the event trigger when it is invoked.
If this parameter is true, the code will
be executed. If this parameter is false,
then the code is not executed.

CurrFieldNo Integer The number of the field that raises the


event.

Order of Event Execution


The relative order of execution of database trigger events, table triggers, and database operations is as follows:

O RDER IT EM EXA M P L E

1 Trigger event (before) OnBeforeDeleteEvent

2 Table trigger OnDelete

3 Global table trigger in codeunit OnDatabaseDelete

4 Database operations Delete the record

5 Trigger event (after) OnAfterDeleteEvent


Page trigger events
Page Trigger events are raised automatically by the system when it performs certain operations in a page object.
Page trigger events are closely associated with the standard page triggers, such as OnOpenPage, OnClosePage,
and OnAction.
Available Page Trigger Events
The following table describes the available page trigger events:

T RIGGER EVEN T SIGN AT URE DESC RIP T IO N

OnAfterActionEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnAction trigger,


Page::<Page Name>, which is called when a user selects an
'OnAfterActionEvent', '<Action
Name>', <SkipOnMissingLicense>, action on the page.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record)

OnAfterGetCurrRecordEvent Trigger [EventSubscriber(ObjectType::Page, Executed after the


Event Page::<Page Name>, OnAfterGetCurrRecord trigger, which is
'OnAfterGetCurrRecordEvent', '',
<SkipOnMissingLicense>, called after the current record is
<SkipOnMissingPermission>)] retrieved from the table.
local procedure MyProcedure(var
Rec: Record)

OnAfterGetRecordEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the


Page::<Page Name>, OnAfterGetCurrRecord trigger, which is
'OnAfterGetRecordEvent', '',
<SkipOnMissingLicense>, called after the record is retrieved from
<SkipOnMissingPermission>)] the table but before it is displayed to
local procedure MyProcedure(var the user.
Rec: Record)

OnAfterValidateEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnValidate (Page


Page::<Page Name>, fields) trigger, which is called when a
'OnAfterValidateEvent', '<Control
Name>', <SkipOnMissingLicense>, field loses focus after its value has
<SkipOnMissingPermission>)] been changed.
local procedure MyProcedure(var
Rec: Record; var xRec: Record)

OnBeforeActionEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed before the OnAction trigger,


Page::<Page Name>, which is called when a user selects an
'OnBeforeActionEvent', '<Action
Name>', <SkipOnMissingLicense>, action on the page.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record)

OnBeforeValidateEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed before the OnValidate (Page


Page::<Page Name>, fields) trigger, which is called when a
'OnBeforeValidateEvent', '<Control
Name>', <SkipOnMissingLicense>, field loses focus after its value has
<SkipOnMissingPermission>)] been changed.
local procedure MyProcedure(var
Rec: Record; var xRec: Record)

OnClosePageEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnClosePage


Page::<Page Name>, trigger, which is called when page
'OnClosePageEvent', '',
<SkipOnMissingLicense>, closes after the OnQueryClosePage
<SkipOnMissingPermission>)] trigger is executed.
local procedure MyProcedure(var
Rec: Record)
T RIGGER EVEN T SIGN AT URE DESC RIP T IO N

OnDeleteRecordEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnDeleteRecord


Page::<Page Name>, trigger, which is called before a record
'OnDeleteRecordEvent', '',
<SkipOnMissingLicense>, is deleted from a table.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; var AllowDelete:
Boolean)

OnInsertRecordEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnInsertRecord


Page::<Page Name>, trigger, which is called before a record
'OnInsertRecordEvent', '',
<SkipOnMissingLicense>, is inserted in a table.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; BelowxRec: Boolean;
var xRec: Record; var
AllowInsert: Boolean)

OnModifyRecordEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnModifyRecord


Page::<Page Name>, trigger, which is called before a record
'OnModifyRecordEvent', '',
<SkipOnMissingLicense>, is modified in a table.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; var xRec: Record;
var AllowModify: Boolean)

OnNewRecordEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnNewRecord


Page::<Page Name>, trigger, which is called before a new
'OnNewRecordEvent', '',
<SkipOnMissingLicense>, record is initialized.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; BelowxRec: Boolean;
var xRec: Record)

OnOpenPageEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnOpenPage


Page::<Page Name>, trigger, which is called after a page is
'OnOpenPageEvent', '',
<SkipOnMissingLicense>, initialized and run.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record)

OnQueryClosePageEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnQueryClosePage


Page::<Page Name>, trigger, which is called as a page closes
'OnQueryClosePageEvent', '',
<SkipOnMissingLicense>, and before the OnClosePage trigger
<SkipOnMissingPermission>)] executes.
local procedure MyProcedure(var
Rec: Record; var AllowClose:
Boolean)

The following table describes the parameters of the trigger events:

PA RA M ET ER TYPE DESC RIP T IO N

Rec Record The table that used page that raises


the event.

xRec Record The table that used page that raises


the event.
PA RA M ET ER TYPE DESC RIP T IO N

AllowDelete Boolean Specifies whether the OnDeleteRecord


trigger call was successful and the
record can be deleted. If this
parameter is true, the code will be
executed. If this parameter is false,
then the code is not executed.

AllowModify Boolean Specifies whether the OnModifyRecord


trigger call was successful and the
record can be modified. If this
parameter is true, the code will be
executed. If this parameter is false,
then the code is not executed.

BelowxRec Boolean Specifies whether the new record was


inserted after the last record in the
table (xRec).

AllowClose Boolean Specifies whether to the page can


close. If this parameter is true, the
code will be executed. If this parameter
is false, then the code is not executed.

See Also
Events in AL
Publishing Events
Raising Events
Subscribing to Events
Isolated Events
Publishing Events
2/6/2023 • 3 minutes to read • Edit Online

The first phase of implementing an event is publishing the event. Publishing an event exposes it in the
application. It provides hook up points for subscribers to register to the event, and eventually handle the event if
it's raised. An event is published by adding an AL method that is set up as an event publisher.
Business and integration events require that you manually create an event publisher method for each
event that you want to publish. An event publisher method declares the event in the application and
makes it available for subscription. However, it doesn't raise the event. After an event is published, you
can raise it in your application from where event subscribers can react and handle the event.
Trigger events don't require that you create publisher methods. Trigger events are predefined event
publisher methods that are called automatically at runtime. So trigger events are readily available to
subscribers by default.

Creating an event publisher method to publish business and


integration events
You create an event publisher method the same way you create any method in AL. But there are specific
attributes that you set to make it an event publisher. Additionally, an event publisher method has the following
requirements and restrictions that you must follow, otherwise you can't compile your code changes:
An event publisher method can't include any code except comments.
An event publisher method can't have a return value, variables, or text constants.
The following procedure provides an outline of the tasks that are involved in creating an event publisher
method for declaring an event.
To create an event publisher method
1. Decide where you want to include the event publisher method.
You can include an event publisher method in the AL code of any object type, such as codeunit, page, or
table. You can create a new object or use an existing object.

IMPORTANT
If you include the event publisher method in a page object, the page must have a source table. Otherwise, you
can't successfully create an event subscriber method to subscribe to the event.

2. Add an AL method to the object.


If you don't want the event publisher to be raised from other objects than the one defining it, make it a
local method by affixing it with local . The event still remains available to event subscribers from other
objects.
Give the method a name that has the format On[Event], where [Event] is text that indicates what occurred,
such as OnAddressLineChanged .
3. Decorate the method with either the Integration attribute or Business attribute as follows:
[IntegrationEvent(IncludeSender : Boolean, GlobalVarAccess : Boolean)]

or

[BusinessEvent(IncludeSender : Boolean)]

TIP
Use the teventint snippet for an integration event or the teventbus snippet for a business event to get
started.

For more information about integration and business events, see Event Types.
4. Add parameters to the method as needed.
You can include as many parameters of any type as necessary.
Make sure to expose enough information. Parameters enable subscriber methods to add value to the
application. However, don't expose unnecessary parameters that may constrain you from changing or
extending methodically in the future.
You can now add code to the application that raises the event by calling the event publisher method. You can
also create subscriber methods that handle the event when it's raised.

Example
This example creates the codeunit 50100 MyPublishers to publish an integration event. The event is published
by adding the global method called OnAddressLineChanged . The event takes a single text data type parameter.

NOTE
This example is part of a larger, simple scenario where when users change the address of a customer on the page 21
Customer Card , you want to check that the address doesn't include a plus sign (+). If it does, you want to display a
message. To accomplish this, you will publish an event that is raised when the Address field on Customer Card is
changed, and add an event subscriber method to that includes logic that checks the address value and returns a message
to the user if it contains a plus sign. For a complete description of this scenario and all the code involved, see Event
Example.

codeunit 50100 MyPublishers


{
[IntegrationEvent(false, false)]
procedure OnAddressLineChanged(line : Text[100]);
begin
end;
}

The next step is to raise this event in the application. To see an example for how this event is raised, go to Raising
Event Example.

See Also
Raising Events
Subscribing to Events
Events Dynamics 365
Raising Events
2/6/2023 • 2 minutes to read • Edit Online

After an event has been published by an event publisher method, you can modify the application to raise the
event where it is needed. Subscribers of an event will not react on the event until it is raised in the application.
To raise an event, you add logic in AL code of the application to call the event publisher method that declares the
event. The procedure for calling the event publisher method is the same as calling any other method in AL.
When the code that calls the event publisher method is run, all event subscriber methods that subscribe to the
event are run. If there are multiple subscribers, the subscriber methods are run one at a time in no particular
order. You cannot specify the order in which the subscriber methods are called.
If there are no subscribers to the published event, then the line of code that calls the event publisher method is
ignored and not executed.

Snippet support
Typing the shortcut teventsub will create the basic event subscriber syntax when using the AL Language
extension in Visual Studio Code.

TIP
Typing the keyboard shortcut Ctrl+Space displays IntelliSense to help you fill in the attribute arguments and to discover
which events are available to use.

Example
This example uses a page extension object 50100 MyCustomerExt to modify the page 21 Customer Card so
that an event is raised when a user changes the Address field. This example assumes that the event has already
been published by the event publisher method OnAddressLineChanged in a separate codeunit called 50100
MyPublishers .

NOTE
This example is part of a larger, simple scenario where when users change the address of a customer on the page 21
Customer Card , you want to check that the address does not include a plus sign (+). If it does, you want to return a
message to the user. For a description of this scenario and all the code involved, see Event Example.

In the code that follows, the page extension object modifies the OnBeforeValidate trigger of the Customer
Card page to raise the event OnAddressLineChanged which includes the new value of the Address field.
pageextension 50100 MyCustomerExt extends "Customer Card"
{
layout
{
modify(Address)
{
trigger OnBeforeValidate();
var
Publisher: Codeunit MyPublishers;
begin
Publisher.OnAddressLineChanged(Rec.Address);
end;
}
}
}

To learn about how the event used in this example is published, see Publishing Events Example.
The next step would be to subscribe to the event to handle to condition. To see an example of how to subscribe
to this event, see Subscribing to Events Example.

See Also
Publishing Events
Subscribing to Events
Events in AL
Subscribing to Events
2/6/2023 • 5 minutes to read • Edit Online

To handle events, you design event subscribers. Event subscribers determine what actions to take in response to
an event that has been raised. An event subscriber is a method that listens for a specific event that is raised by
an event publisher. The event subscriber includes code that defines the business logic to handle the event. When
the published event is raised, the event subscriber is called and its code is run.
Subscribing to an event tells the runtime that the subscriber method must be called whenever the publisher
method is run, either by code (as with business and integration events) or by the system (as with trigger events).
The runtime establishes the link between an event raised by the publisher and its subscribers, by looking for
event subscriber methods.
There can be multiple subscribers to the same event from various locations in the application code. When an
event is raised, the subscriber methods are run one at a time in no particular order. You can't specify the order in
which the subscriber methods are called.

Creating an event subscriber method


You create an event subscriber method just like other methods except that you specify properties that set up the
subscription to an event publisher. The procedure is slightly different for database and page trigger events than
business and integration events. Business and integration events are raised by event publisher methods in
application code. Trigger events are predefined system events that are raised automatically on tables and pages.
For an explanation about the different types, see Event Types.
To create an event subscriber method
1. Decide which codeunit to use for the event subscriber method.
You can create a new codeunit or use an existing one.
2. Add an AL method to the codeunit.
We recommend that you give the method a name that indicates what the subscriber does, and has the
format [Action][Event]. [Action] is text that describes what the method does. [Event] is the name of the
event publisher method to which it subscribes.
3. Add code to the method for handling the event.
4. Decorate the event subscriber method with the EventSubscriber attribute.

[EventSubscriber(ObjectType::<Event Publisher Object Type>, <Event Publisher Object>, '<Published


Event Name>', '<Published Event Element Name>', <SkipOnMissingLicense>, <SkipOnMissingPermission>)]

Set the arguments according to the following table. For optional arguments, if you don't want to set a
value, use an empty value ( '' ). In this case, the default value, if any, is used.

A RGUM EN T DESC RIP T IO N O P T IO N A L


A RGUM EN T DESC RIP T IO N O P T IO N A L

<Event Publisher Object Type> Specify the type of object that no


publishes the event. This argument
can be Codeunit , Page , Report ,
Table , or XMLPort .

<Event Publisher Object> Specify the object that publishes the no


event. You can set this argument to
the ID, such as 50100 , or the
recommended way is to use the
object name by using the syntax
<Object Type>::"<Object Name>"
, such as
Codeunit::"MyPublishers" , or for
database triggers
Database::"Customer" .

<Published Event Name> Specify the name of method that no


publishes the event in the object
that is specified by the
<Event Publisher Object>
parameter.

<Published Event Element Name> Specifies the table field that the no
trigger event pertains to. This
argument only requires a value for
database trigger events, that is,
when the
<Event Publisher Object Type>
is set to Table and the
<Published Event Name>
argument is a validate trigger event,
such as OnAfterValidateEvent .

<SkipOnMissingLicense> Set to true to skip the event yes


subscriber method call if the user's
license doesn't cover the event
subscriber codeunit. If false , an
error is thrown and the code
execution stops. false is the
default.

<SkipOnMissingPermission> Set to true to skip the event yes


subscriber method call if the user
doesn't have the correct permissions
the event subscriber codeunit. If
false , an error is thrown and the
code execution stops. false is the
default.

TIP
There are a couple of things that can make defining an event subscriber method easier. You can use the
teventsub snippet to get started. Then, typing the keyboard shortcut Ctrl+Space displays IntelliSense to help
you fill the attribute arguments and discover which events are available. Or, use the Shift+Alt+E keyboard
shortcut to look up the event you want to subscribe to and insert the code.
5. Optionally, set the codeunit's EventSubscriberInstance property to specify how the event subscriber
method will be bound to the instance of this codeunit.
For more information, see EventSubscriberInstance Property.

Example 1
This example creates the codeunit 50101 MySubscribers to subscribe to an event that has been published by
the event publisher method called OnAddressLineChanged in the codeunit 50100 MyPublishers . The event is
raised by a change to the Address field on page 21 Customer Card . This example assumes:
The codeunit 50100 MyPublishers with the event publisher method OnAddressLineChanged already exists.
For an example, see Publishing Event Example.
The code for raising the OnAddressLineChanged event has been added to the Customer Card page. For an
example, see Raising Event Example.
The following code creates a codeunit called 50101 MySubscribers that includes an event subscriber method,
called CheckAddressLineOnAddressLineChanged . The method includes code for handling the published event.

codeunit 50101 MySubscribers


{
EventSubscriberInstance = StaticAutomatic;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"MyPublishers", 'OnAddressLineChanged', '', true,


true)]
procedure CheckAddressLineOnAddressLineChanged(line : Text[100]);
begin
if (StrPos(line, '+') > 0) then begin
Message('Can''t use a plus sign (+) in the address [' + line + ']');
end;
end;
}

NOTE
This example is part of a larger, simple scenario where when users change the address of a customer on the page 21
Customer Card , you want to check that the address does not include a plus sign (+). If it does, you want to return a
message to the user. For a description of this scenario and all the code involved, see Event Example.

Example 2
This example achieves the same as example 1, except it subscribes to the page trigger event
OnBeforeValidateEvent on the Address field instead. By using the page trigger, you avoid creating an event
publisher and adding code to raise the event. The event is raised automatically by the system.
codeunit 50101 MySubscribers
{
EventSubscriberInstance = StaticAutomatic;

[EventSubscriber(ObjectType::Page, Page::"Customer Card", 'OnBeforeValidateEvent', 'Address', true,


true)]
local procedure CheckAddressLineOnBeforeValidateEvent(var Rec : Record Customer)
begin
if (StrPos(Rec.Address, '+') > 0) then begin
Message('Can''t use a plus sign (+) in the address [%1]', Rec.Address);
end;
end;
}

See Also
Publishing Events
Raising Events
Event Types
Events in AL
EventSubscriberInstance Property
EventSubscriber Attribute
Isolated Events in AL
2/6/2023 • 2 minutes to read • Edit Online

You can define a business, integration, or internal event to be an isolated event. An isolated event ensures the
event publisher continues its code execution after calling an event. If an event subscriber's code causes an error,
its transaction and associated table changes will be rolled back. The execution continues to the next event
subscriber, or it will be handed back to the event's caller.

How isolated events work


Isolated events are implemented by separating each event subscriber into its own transaction. The transaction is
created before invoking an event subscriber, then committed afterwards. The following diagram illustrates the
flow.

When an event is raised, the platform gets the first event subscriber. When the event is isolated, an isolated
transaction starts, then the event subscriber is invoked. If an error occurs, the transaction is rolled back, and the
flow is repeated for the next event subscriber. Otherwise, the transaction is committed and the flow is repeated
for the next event subscriber.
NOTE
Read-only transactions are allowed to call isolated events directly, but write transactions should explicitly be
committed before invoking an isolated event. Other wise, the isolated event will be invoked like an
normal event, that is, errors inside an event subscriber will cause the entire operation to fail.

Rollback
Only changes done via Modify/Delete/Insert calls on records of type TableType: Normal will be automatically
rolled back. Other state changes, like HTTP calls, variable alterations, changes to single instance codeunit's
members, won't be rolled back.
For example, if an integer variable that's passed by VAR is modified by a failing event subscriber, its changes will
persist.
Extension installation and upgrade
When the operation is installing, uninstalling, or upgrading extensions, isolated events aren't run isolated. The
events run normally instead.
The reason for this behavior is that these operations require that all operations within them are done in one
transaction. So explicit Commit calls can't be made during the operations.

How to define an isolated event


The BusinessEvent, IntegrationEvent, and InternalEvent attributes include the Isolated boolean argument, for
example:

[InternalEvent(IncludeSender: Boolean, Isolated: Boolean)]

To define an isolated event, set the Isolated argument, which is to true , for example:

[InternalEvent(true, true)]

Example
codeunit 50145 IsolatedEventsSample
{
trigger OnRun()
var
Counter: Integer;
cust : Record Customer;
begin
// Precondition: Customer table isn't empty.
if (cust.IsEmpty) then
Error('Customer table is empty.');

MyIsolatedEvent(Counter);

// Code only reaches this point because the above event is isolated and error thrown in
FailingEventSubscriber is caught.
if (Counter <> 2) then
Error('Both event subscribers should have incremented the counter.');

// Post-condition: Customer table hasn't been truncated.


if (cust.IsEmpty) then
Error('Customer table was truncated, failing event subscriber was not rolled back.');
end;

[InternalEvent(false, true)]
local procedure MyIsolatedEvent(var Counter: Integer)
begin
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::IsolatedEventsSample, 'MyIsolatedEvent', '', false,


false)]
local procedure FailingEventSubscriber(var Counter: Integer)
var
cust: Record Customer;
begin
Counter += 1; // Change will persist even after throwing. Only database changes will be rolled back.

cust.DeleteAll(); // Database changes will be rolled back upon error.

Error('Fail!');

// Code below won't be reached!


Counter += 1;
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::IsolatedEventsSample, 'MyIsolatedEvent', '', false,


false)]
local procedure IncreasingEventSubscriber(var Counter: Integer)
begin
Counter += 1;
end;
}

See Also
Publishing Events
Raising Events
Subscribing to Events
Developing Extensions Using the New Development Environment
Discoverability of Events
2/6/2023 • 2 minutes to read • Edit Online

You subscribe to events to extend application and interact with the base application and other extensions. This
topic describes how to discover events that you can subscribe to without writing the code manually. Using the
Event Recorder , you can record the events that are published and raised while performing the actions of your
scenario. For example, record the events raised when you post a purchase order and identify the events that you
need for your extension. You can retrieve the events in the form of AL snippet code and use them in Visual
Studio Code directly.

Using the Event Recorder


You can launch the event recorder session from Dynamics 365 Business Central. It can be accessed in the
following two ways:
In Dynamics 365 Business Central, search for Event Recorder .
In Visual Studio Code, use the Ctrl+Shift+P keys and select the Open Event Recorder command to open
the Event Recorder page in the Dynamics 365 Business Central web client.

NOTE
The event recorder captures all events that are raised in the same session. If the actions performed by the user are in
another session, then the event recorder will not capture them.

How to record events


The following steps describe how to record events when you are on the Event Recorder page.
1. On the Event Recorder page, in the upper right corner, choose Open this page in a new window .
2. Then on the Event Recorder page, choose Record Events , and then choose the Star t button.
3. In the original window, perform all the actions that you want to record while the event recorder session is on.
For example, post a purchase order.
4. After you have performed the actions of your scenario, navigate back to the window that has the Event
Recorder page open and click the Stop button to finish recording.
All the events raised while performing the actions of your scenario are recorded and can be viewed on as
shown below.
5. Choose Get AL Snippet to get the event subscription code in AL. You can use the AL snippet code in
Codeunits to subscribe to those events.

NOTE
The recorded events are not saved. When you refresh the page, the recorded events disappear.

For more information on how to subscribe to events, see Subscribing to Events.

Recorded Events
All the recorded events display in the order they were called. The Event Recorder page provides information on
the events that were raised including the details whether the raised events were trigger events or custom events.
The custom events are either Business Events or Integration Events. For more information, see Event Types.
You can identify the Event types, additionally, you can discover which object types and methods raised the
events with the details like calling methods, object types, and object names. For more information about Events,
see Events in AL.

See Also
Events in AL
Publishing Events
Raising Events
Subscribing to Events
Debugging in AL
Developing Extensions
Event Example
2/6/2023 • 2 minutes to read • Edit Online

This article includes a simple code example to explain how to use Business Central events. The example uses an
event to verify a customer's address. When a user changes the address of a customer on the page 21
Customer Card , an event is used to check that the address doesn't include a plus sign (+). If it does, a message
is displayed in the client. In this example, you'll add code that:
Publishes an event that is raised when the Address field on Customer Card is changed.
Raises the event from the Customer Card page
Subscribes to the event to check the address value and return a message to the user if it contains a plus sign.

// The following code creates codeunit that publishes the `OnAddressLineChanged` event.

codeunit 50100 MyPublishers


{
[IntegrationEvent(false, false)]
procedure OnAddressLineChanged(line: Text[100])
begin
end;
}

// The following code extends the Customer Card page to raise the `OnAddressLineChanged` event
// when the Address field is changed.
pageextension 50100 MyCustomerExt extends "Customer Card"
{
layout
{
modify(Address)
{
trigger OnBeforeValidate();
var
Publisher: Codeunit MyPublishers;
begin
Publisher.OnAddressLineChanged(Rec.Address);
end;
}
}
}

// The following code creates an event subscriber codeunit.


// It declares the `CheckAddressLine` event subscriber that listens for OnAddressLineChanged event.
// The event subscriber displays a message in the client when '+' is used in the **Address** field.

codeunit 50101 MySubscribers


{
//Set the event subscribers to bind automatically to the event
EventSubscriberInstance = StaticAutomatic;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"MyPublishers", 'OnAddressLineChanged', '', true,


true)]
procedure CheckAddressLine(line: Text[100]);
begin
if (STRPOS(line, '+') > 0) then begin
MESSAGE('Can''t use a plus sign (+) in the address [' + line + ']');
end;
end;
}
TIP
This example binds the event subscriber automatically to the event. You can also bind the event subscriber manually, by
setting the EventSubscriberInstance property. For more information, including an example, see EventSubscriberInstance
property.

See Also
Publishing Events
Raising Events
Subscribing to Events
Events Dynamics 365
Walkthrough: Implementing New Workflow Events
and Responses
2/6/2023 • 12 minutes to read • Edit Online

If a business scenario requires a workflow event or a workflow response that is not supported in a Business
Central solution, you must implement it by extending the application code.
In the Workflow page, the workflow administrator creates a workflow by listing the involved steps on the lines.
Each step consists of a workflow event, moderated by event conditions, and a workflow response, customized by
response options. You define workflow steps by filling fields on workflow lines from fixed lists of event and
response values representing scenarios that are supported by the application code. For more information, see
Set Up Workflows in the business functionality content.
The following procedure describes how to add a new workflow event and a new workflow response and then
register the involved object relations, so that the new elements can be used in workflows. You can then share
your code as an app or a per-tenant extension, for example. The workflow administrator can then select the new
workflow event and response from the Workflow page to incorporate them in new or existing workflow steps.

IMPORTANT
To ensure that custom workflow records are upgraded correctly, you must add new workflow events, workflow responses,
and workflow table relations to dedicated extension points, as described in this procedure. During an upgrade to the next
version, the libraries of workflow events, responses, and table relations are removed and then recreated with the latest
content from Microsoft. By adding your custom workflow records using subscriptions to the Microsoft-provided extension
points, you ensure that your custom record library gets recreated after an upgrade.

NOTE
This topic refers to two types of events:
Workflow event: An occurrence in the application that users in the client can select from the Workflow page to define
workflow steps. For more information, see Workflows in Dynamics 365 Business Central in the business functionality
content.
Event: The declaration of the occurrence or change in the application. Workflow events typically subscribe to events.
For more information, see Events in AL.

The development work involved in creating a new workflow event and a related workflow response consists of
the following tasks, as a minimum:
1. Create a workflow event
a. Create a workflow event code that identifies the workflow event
b. Add the workflow event code to the Workflow Event table
c. Create and publish an event that the workflow event subscribes to
d. Raise the event
e. Subscribe to the event and implement the workflow event
2. Create a workflow response
a. Create a workflow response code that identifies the workflow response
b. Add the workflow response code to the Workflow Response table
c. Implement the workflow response
d. Enable that the workflow response can be executed
e. Add a new workflow response option
3. Register workflow event/response combinations needed for the new workflow response
4. Register workflow event hierarchies needed for the new workflow event
5. Creating table relations between entities used when the new workflow event and response are used

NOTE
Data and code samples in this procedure refer loosely to a workflow step of sending a notification when a purchase
header is posted. However, the procedure alone does not result in a complete solution. The purpose of the walkthrough is
simply to illustrate the process.

Workflow event
In this section, we'll create a code to identify the workflow event, add the workflow event to the library, create an
event that the workflow event subscribes to, raise the event, and then subscribe to the event and implement the
workflow event.
Each subsection takes you through the discrete steps.
To create a workflow event code that identifies the workflow event
1. Create a new .al file, such as MyWorkflowEvents.codeunit.al, and add a codeunit that will be used for new
workflow events. Name it to reflect that it is used to identify the new workflow event, such as
MyWorkflowEvents .

2. Add a method in the codeunit. Optionally, use the shortcut tprocedure . Name the method to reflect that
it is used to identify the workflow event, such as MyWorkflowEventCode , and make it take 128 characters of
code as a parameter.

TIP
The terminology can be a bit confusing here. This method is not an AL event. It's a method that declares the workflow
event, and it will subscribe to an AL event that, when triggered, will trigger the workflow event.

Your MyWorkflowEvents.codeunit.al file now looks like this:

codeunit 50101 MyWorkflowEvents


{
procedure MyWorkflowEventCode(): code[128];
begin
end;
}

To add the workflow event code to the Workflow Event table


1. Create another method in the codeunit. Name it to reflect that it is used to add the workflow event to the
library, such as AddMyWorkflowEventsToLibrary .
This method will subscribe to the OnAddWorkflowEventsToLibrary method in the Workflow Event Handling
codeunit in the base application, so you must set the EventSubscriber attribute, and you must add code
that handles the event.
The following code illustrates the new method in the MyWorkflowEvents codeunit:

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Event Handling",


'OnAddWorkflowEventsToLibrary', '', true, true)]
procedure AddMyWorkflowEventsToLibrary()
var
WorkflowEventHandling: Codeunit"Workflow Event Handling";
begin
WorkflowEventHandling.AddEventToLibrary(MyWorkflowEventCode(), Database::"Purchase Header", 'My
workflow event description', 0, false);
end;

To publish an event that the workflow event subscribes to


1. Create another codeunit, such as MyEvents.codeunit.al, and add a method that publishes your event.
Name the method to reflect that it is used as the publisher event, such as OnAfterPostPurchaseHeader .

codeunit 50102 MyEvents


{
[IntegrationEvent(false, false)]
procedure OnAfterPostPurchaseHeader(PurchaseHeader: Record "Purchase Header")
begin
end;
}

Select the event type that is relevant for the workflow event, such as Integration. For more information,
see Event Types.
To raise the event
1. Create an object or an extension object to add the code that will raise the event that triggers the workflow
event, such as the Purch.-Post codeunit.
The following code raises the event by extending the Purchase Order page object in a new file,
MyPurchOrder.PageExt.al .

pageextension 50100 WFW_PurchaseOrder extends "Purchase Order"


{
layout
{
modify(Status)
{
trigger OnBeforeValidate();
var
MyEvents: Codeunit MyEvents;
begin
MyEvents.OnAfterPostPurchaseHeader(Rec)
end;
}
}
}

For more information, see Raising Events.


To subscribe to the event and implement the workflow event
1. Go back to the MyWorkflowEvents.codeunit.al file and add another method in the MyWorkflowEvents
codeunit. Name the new method to reflect that it is used to subscribe to and implement the workflow event,
such as RunWorkflowOnAfterPostPurchaseHeader .

The following code illustrates the new workflow event that subscribes to your previously created event:

[EventSubscriber(ObjectType::Codeunit, Codeunit::MyEvents, 'OnAfterPostPurchaseHeader', '', true, true)]


local procedure RunWorkflowOnAfterPostPurchaseHeader(var PurchaseHeader: Record "Purchase Header")
var
WorkflowManagement: Codeunit "Workflow Management";
begin
WorkflowManagement.HandleEvent(MyWorkflowEventCode, PurchaseHeader);
end;

Another task that you can perform at this point is to specify which filter fields appear in the Workflow Event
Conditions page.
For more information, see Subscribing to Events.
You have now created a new workflow event. Next, we'll create a new workflow response that relates to the
workflow event.

Workflow response
Create a new .al file, such as MyWorkflowResponses.codeunit.al, with code to identify the workflow response,
add the workflow response code to the library, implement the workflow response, and then enable that the
workflow response can be executed.
To create a workflow response code that identifies the workflow response
1. Add a new codeunit that will be used for the new workflow responses. Name it to reflect that it handles
your new responses, such MyWorkflowResponses .
2. Add a method in the codeunit. Name the method to reflect that it is used to identify the workflow
response, such as MyWorkflowResponseCode with a return value of code (128).
To add the workflow response code to the Workflow Response table
1. Add another method in the codeunit that will be the event subscriber. Name it to reflect that it is used to
add the workflow response to the library, such as AddMyWorkflowResponsesToLibrary and set it to subscribe
to the OnAddWorkflowResponsesToLibrary method in the Workflow Response Handling` codeunit.

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Event Handling",


'OnAddWorkflowEventPredecessorsToLibrary', '', false, false)]
local procedure AddWorkflowEventHierarchiesToLibrary(EventFunctionName: Code[128])
begin
end;

2. Add a local variable for the codeunit:

[...]
var
WorkflowResponseHandling: Codeunit "Workflow Response Handling";

3. In the method, write code that registers the response, so that you end up with something like the
following code.
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Response Handling",
'OnAddWorkflowResponsesToLibrary', '', true, true)]
local procedure AddMyWorkflowResponsesToLibrary()
var
WorkflowEventHandling: codeunit "Workflow Event Handling";
begin
WorkflowResponseHandling.AddResponseToLibrary(MyWorkflowResponseCode, Database::"Purchase
Header", 'Send a notification.', 'GROUP 0');
End
end;

NOTE
In the To add a new workflow response option section, you will change the GROUP value to 50100. This way, you'll be
able to see the workflow in action.

The codeunit now looks something like this:

codeunit 50103 MyWorkflowResponses


{
procedure MyWorkflowResponseCode(): code[128];
begin
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Response Handling",


'OnAddWorkflowResponsesToLibrary', '', true, true)]
local procedure AddMyWorkflowResponsesToLibrary()
var
WorkflowResponseHandling: Codeunit "Workflow Response Handling";
begin
WorkflowResponseHandling.AddResponseToLibrary(MyWorkflowResponseCode, Database::"Purchase Header",
'Send a notification.', 'GROUP 0');
end;
}

To implement the workflow response


1. Create another method in the codeunit. Name it to reflect that it is used to implement the workflow
response, such as MyWorkflowResponse , that takes a parameter based on the Purchase Header table.
2. In the method, write code that handles the response, so that you end up with something like the
following code.

procedure MyWorkflowResponse(PurchaseHeader: Record "Purchase Header")


begin
Message('Status change on: %1 %2', PurchaseHeader."Document Type", PurchaseHeader."No.");
end;

To enable that the workflow response can be executed


1. Create another method in the codeunit that subscribes to the OnExecuteWorkflowResponse event on the
Workflow ResponseHandling codeunit. Name it to reflect that it is used to enable the new workflow
response to be executed alongside existing workflow responses, such as ExecuteMyWorkflowResponses .
2. In the event subscriber method, write code that enables the response, so that you end up with something
like the following code.
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Response Handling",
'OnExecuteWorkflowResponse', '', true, true)]
procedure ExecuteMyWorkflowResponses(ResponseWorkflowStepInstance: Record "Workflow Step Instance";
var ResponseExecuted: Boolean; var Variant: Variant; xVariant: Variant)
var
WorkflowResponse: record "Workflow Response";
begin
if WorkflowResponse.GET(ResponseWorkflowStepInstance."Function Name") then
case WorkflowResponse."Function Name" of
MyWFResponseCode:
BEGIN
MyWorkflowResponse(Variant);
ResponseExecuted := TRUE;
END;
END;
end;

You'll update this method in step 8 in the next section.


To add a new workflow response option
1. Create a table extension object that extends table 1523, Workflow Step Argument , such as
MyWorkflowStepArgument.TableExt.al.
2. Add a field that reflects your new response option, such as My New Response Option .

tableextension 50100 WFW_WorkflowStepArgument extends "Workflow Step Argument"


{
fields
{
field(50100; "My New Response Option"; Text[100])
{
}
}
}

3. Create a page extension object that extends page 1523, Workflow Response Options , such as
MyworkflowStepArgument.PageExt.al.
4. Add a group and a control for the new field.

pageextension 50101 WFW_WorkflowResponseOptions extends "Workflow Response Options"


{
layout
{
addlast(content)
{
group(Group50100)
{
Visible = Rec."Response Option Group" = 'GROUP 50100';
ShowCaption = false;

field(MyNewResponseOption; Rec."My New Response Option")


{
ApplicationArea = All;
}
}
}
}
}

Here, the Visibility property of the group is set to "Response Option Group" = 'GROUP 50100' , but you can
set it to another value.
5. Go back to MyWorkflowResponses.codeunit.al and the ´AddMyWorkflowResponsesToLibrary` method.
6. In the method code, change 'GROUP 0' to 'GROUP 50100' .

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Response Handling",


'OnAddWorkflowResponsesToLibrary', '', true, true)]
local procedure AddMyWorkflowResponsesToLibrary()
var
WorkflowResponseHandling: Codeunit "Workflow Response Handling";
begin
WorkflowResponseHandling.AddResponseToLibrary(MyWorkflowResponseCode, Database::"Purchase
Header", 'Send a notification.', 'GROUP 50100');
end;

7. To use the new option in the MyWorkflowResponse method, proceed to add a local parameter and a local
variable and show a message as the response.

local procedure MyWorkflowResponse(PurchaseHeader: Record "Purchase Header"; WorkflowStepInstance:


Record "Workflow Step Instance")
var
WorkflowStepArgument: Record "Workflow Step Argument";
begin
if WorkflowStepArgument.Get(WorkflowStepInstance.Argument) then;

Message('Status change on: %1 %2.\%3', PurchaseHeader."Document Type", PurchaseHeader."No.",


WorkflowStepArgument."My New Response Option")
end;

8. In the ExecuteMyWorkflowResponses method, make the following code change:


Change from this code: MyWorkflowResponse(Variant);

Change to this code: MyWorkflowResponse(Variant,ResponseWorkflowStepInstance);

You have now created the actual workflow event and response. Proceed to perform various tasks that
enable them to be used in workflows.

Register workflow event/response combinations


In this section, you'll add new workflow event/response combinations to table 1509 WF Event/Response
Combination so that they appear correctly in the Workflow Events and Workflow Responses pages.
To register workflow event/response combinations needed for the new workflow response
1. Open the codeunit that you created in the Workflow response section, My Workflow Responses .
2. Create another method in the codeunit that subscribes to the
OnAddWorkflowResponsePredecessorsToLibrary event on the Workflow Response Handling codeunit . Name it
to reflect that it is used to add the workflow event/response combinations to table 1509 WF
Event/Response Combination , such as AddMyWorkflowEventResponseCombinationsToLibrary .
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Response Handling",
'OnAddWorkflowResponsePredecessorsToLibrary', '', false, false)]
local procedure AddMyworkflowEventOnAddWorkflowResponsePredecessorsToLibrary(ResponseFunctionName:
Code[128])
var
MyWorkflowEvents: Codeunit MyWorkflowEvents;
WorkflowResponseHandling: Codeunit "Workflow Response Handling";
begin
Case ResponseFunctionName of
MyWorkflowResponseCode():
WorkflowResponseHandling.AddResponsePredecessor(MyWorkflowResponseCode(),
MyWorkflowEvents.MyWorkflowEventCode());
End
end;

In the method, write code that registers event/response combinations that you want to support in your
application, using a CASE statement, such as the code in the example above.
You can also do this work from the user interface on page 1507 Workflow-Event-Response-
Combinations .

Register workflow event hierarchies


In this section, you'll add new workflow event/event combinations to table 1509 WF Event/Response
Combination so that the workflow events appear in the correct hierarchy in the Workflow Events page.
To register workflow event hierarchies needed for the new workflow event
1. Go back to the MyWorkflowEvents.codeunit.al file with the codeunit that you created in the To create a
workflow event code that identifies the workflow event section, My Workflow Events .
2. Create another method in the codeunit that subscribes to the OnAddWorkflowEventPredecessorsToLibrary
event on the Workflow Event Handling codeunit. Name it to reflect that it is used to add the workflow
event hierarchies to table 1509 WF Event/Response Combination , such as
AddWorkflowEventHierarchiesToLibrary .

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Event Handling",


'OnAddWorkflowEventPredecessorsToLibrary', '', false, false)]
local procedure AddWorkflowEventHierarchiesToLibrary(EventFunctionName: Code[128])
var
WorkflowEventHandling: codeunit "Workflow Event Handling";
begin
Case EventFunctionName of
MyWorkflowEventCode():
//WorkflowEventHandling.AddEventPredecessor(MyWorkflowEventCode(),
WorkflowEventHandling./*[Add your predecessor event code]*/);
;
End
end;

In the method, write code that registers event hierarchies that you want to support in your application,
using a CASE statement, such as the code in the example above.
You can also do this work from the user interface on page 1506 Workflow-Event-Hierarchies .

Create table relations


Workflows events can be executed on different types of records. To keep track of these, you must define
relations between the involved records. In this section, you'll create relationships between the entities that are
used when the new workflow event and response are used.
To create table relations between entities that are processed when the new workflow event and response are
used in workflows
1. Got back to the MyWorkflowEvents.codeunit.al file with the codeunit that you created in the To create a
workflow event code that identifies the workflow event section, My Workflow Events .
2. Create another method in the codeunit that subscribes to the OnAddWorkflowTableRelationsToLibrary
event on the Workflow Event Handling codeunit. Name it to reflect that it is used add workflow table
relations in table 1505 Workflow Table Relation , such as AddWorkflowTableRelationsToLibrary .

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Event Handling",


'OnAddWorkflowTableRelationsToLibrary', '', false, false)]
local procedure AddWorkflowTableRelationsToLibrary()
var
WorkflowSetup: Codeunit "Workflow Setup";
begin
WorkflowSetup.InsertTableRelation(Database::"Purchase Header", 1, Database::"Approval Entry", 2);
end;

In the method, write code that registers table relations that you want to support in your application, such
as the example above.
You can also do this work from the user interface on page 1509 Workflow Table-Relations .
You have now enabled a new workflow scenario by implementing the required workflow event and response in
the application code. The workflow administrator can now select the workflow event and workflow response
from the Workflow page to define new or edit existing workflows. For more information, see Set Up Workflows
in the business functionality content.

See Also
Workflows in Dynamics 365 Business Central
Set Up Workflows
Event Example
Events in AL
Page Extension Object
Table Extension Object
Codeunit Object
Table Object
Get Started with AL
Development and Administration for Dynamics 365 Business Central
Notifications
2/6/2023 • 5 minutes to read • Edit Online

Notifications provide a programmatic way to send non-intrusive information to the User Interface (UI) in the
Web client. Notifications differ from messages initiated by the Message method. Messages are modal, which
means users are typically required to address the message and take some form of corrective action before they
continue working. On the other hand, notifications are non-modal. Their purpose is to give users information
about a current situation, but do not require any immediate action or block users from continuing with their
current task. For example, you could have a notification that a customer's credit limit is exceeded.

Notifications in the UI
In the UI, notifications appear in the Notification bar (similar to validation errors) at the top of the page on
which a user is currently working. The user can then choose to dismiss the notification, which clears it. Or, if
actions are defined on notification, the user can choose one of the actions.
There can be multiple notifications. The notifications appear in chronological order from top to bottom.
Notifications remain for the duration of the page instance or until the user dismisses them or takes action on
them.
Notifications that are defined on sub-pages, for example in parts and FactBoxes, appear in the same
Notification bar.
Validation errors on the page will be shown first.

Notifications in the development environment


By using the Notification and NotificationScope data types and methods in AL, you can add code to send
notifications to users. The following table provides an overview of the available methods. The sections that
follow provide additional information about how to create notifications.

M ET H O D DESC RIP T IO N

Message Specifies the content of the notification that appears in the


UI.

Scope Specifies the scope in which the notification appears.

Send Sends the notification to be displayed by the client.

AddAction Adds an action on the notification.

SetData Sets a data property value for the notification

GetData Gets a data property value from the notification.

Recall Recalls a sent notification.

Creating and sending a notification


You create a notification by using the Message and Send methods. The Message method defines the message
part of the notification. When the Send method is called, the notification is sent to the client and content of the
message is displayed.

MyNotification.Message := 'This is a notification';


MyNotification.Send();

The Send method call should be the last statement in the notification code, after any AddAction or SetData
method calls for the notification instance.

Defining the notification scope


The scope determines where the notification is broadcast in the client. There are two different scopes:
LocalScope and GlobalScope.
A LocalScope notification appears in context of the user's current task, that is, on the page the user is
currently working on. LocalScope is the default.
A GlobalScope notification is not directly related to the current task, and will appear regardless of which
page the user is viewing.

NOTE
GlobalScope is currently not supported. This will be implemented in a future release.

The following code creates a notification in the LocalScope:

MyNotification.Message := 'This is a notification';


MyNotification.Scope := NotificationScope::LocalScope;
MyNotification.Send();

Adding actions on a notification


You add actions on notifications by using the AddAction method. This method provides a way for you to create
interactive notifications. By default, users have the option to dismiss the notifications. However, there might be
cases where you want to provide users with different actions that they can take to address the notification, like
opening an associated page for modifying data.
Conceptually, a notification action calls a method in a specified codeunit, passing the notification object in the
call. The method includes the business logic for handling the action.

MyNotification.Message := 'This is a notification';


MyNotification.Scope := NotificationScope::LocalScope;
MyNotification.AddAction('Action 1',Codeunit::"Action Handler",'RunAction1');
MyNotification.AddAction('Action 2',Codeunit::"Action Handler",'RunAction2');
MyNotification.Send();

The basic steps for adding an action are as follows:


1. Create a global method in a new or existing codeunit. The method must have a Notification data type
parameter for receiving the notification object.
2. Add AL code to the method for handling the action.
3. Specify the codeunit and method in the AddAction method call.
IMPORTANT
You can have more than one action on a notification. A LocalScope notification can have up to 3 actions. A GlobalScope
notification can have up to 2 actions.

Sending data with a notification


You use the SetData and GetData methods to add data to a notification, which is typically needed when actions
are invoked. The SetData method sets, or adds, data to the notification. The data is defined as text in a key-value
pair. With the GetData method, you can then retrieve the data again.
The following code sets data for a notification:

MyNotification.Message := 'This is a notification';


MyNotification.Scope := NotificationScope::LocalScope;
MyNotification.SetData('Created',Format(CurrentDateTime,0,9));
MyNotification.SetData('ID',Format(CreateGuid(),0,9));
MyNotification.AddAction('Action 1',Codeunit::"Action Handler",'RunAction1');
MyNotification.AddAction('Action 2',Codeunit::"Action Handler",'RunAction2');
MyNotification.Send();

The following code gets the data for a notification:

DataValue := MyNotification.GetData('Created');
DataValue := MyNotification.GetData('ID');

Example
This simple example illustrates how notifications work and provides some insight into how you can use them.
This example extends page 42 Sales Order of the CRONUS International Ltd. demonstration database
according to the following:
The code compares a customer's balance with their credit limit. If the balance exceeds the credit limit, a
notification is sent to the client.
The notification includes an action, which has the caption Change credit limit , that opens page 21
Customer Card . This enables the user to increase the credit limit.
To complete the example, follow these steps:
1. Create a page extension object that extends page 42 Sales Order , and add the notification code on the
OnOpenPage trigger.
pageextension 50100 CreditBalanceNotification extends "Sales Order"
{

trigger OnOpenPage()
var
Customer: Record Customer;
CreditBalanceNotification: Notification;
OpenCustomer: Text;
Text003: Label 'The current balance exceeds the credit limit.';
Text004: Label 'Change credit limit';
begin
Customer.Get("Sell-to Customer No.");
if Customer."Balance (LCY)" > Customer."Credit Limit (LCY)" then begin
//Create the notification
CreditBalanceNotification.Message(Text003);
CreditBalanceNotification.Scope := NotificationScope::LocalScope;
//Add a data property for the customer number
CreditBalanceNotification.SetData('CustNumber', Customer."No.");
//Add an action that calls the ActionHandler codeunit, which you define in the next step.
CreditBalanceNotification.AddAction(Text004, Codeunit::"ActionHandler", 'OpenCustomer');
//Send the notification to the client.
CreditBalanceNotification.Send();
end;
end;
}

2. Create a codeunit called ActionHandler for handling the notification action. Add a global method called
OpenCustomer that has a Notification data type parameter called CreditBalanceNotification for
receiving the Notification object, and include the following code on the method:

codeunit 50100 ActionHandler


{
trigger OnRun()
begin

end;

procedure OpenCustomer(CreditBalanceNotification: Notification)


var
CustNumber: Text;
CustNo: Text;
CustRec: Record Customer;
CustPage: Page "Customer Card";
begin
//Get the customer number data from the SetData() call.
CustNo := CreditBalanceNotification.GetData('CustNumber');
// Open the Customer Card page for the customer.
if CustRec.Get(CustNo) then begin
CustPage.SetRecord(CustRec);
CustPage.Run();
end else begin
Error('Could not find Customer: ' + CustNo);
end;
end;
}

See Also
Notification Data Type
Developing Extensions
Get Started with AL
Reports Overview
2/6/2023 • 2 minutes to read • Edit Online

You can use reports to print or display information from a database. Use reports to structure and summarize
information to print documents, such as invoices. For example, create a report that lists all customers and orders
that have been added by each customer. Also, create a report that is automatically filled with the relevant
information for an invoice.
Reports can also be used to process data without printing or displaying content. For example, use a report to
automate updating all prices in an item list. It can be easier to create a report to process data instead of a
codeunit to do the same processing because you can use:
Request page functionality to select options and filters for data items, which are available in a report but
are difficult to add to a codeunit. For more information, see Request Pages.
Report data items instead of writing code to open tables and retrieve records.
Data modeling, which is available when you design reports.

Creating reports
Creating a report involves two primary tasks. First, you create a report object and design the dataset. The
dataset determines the data that is extracted or calculated from the Dynamics 365 Business Central database
tables that can be used in a report. After the dataset has been designed, you design the visual layout of the
report. There are three types of report layouts that you can create: layouts using report definition language
(RDL), Word report layouts, and Excel report layouts. Another option is to extend the functionality of an existing
report with a Report Extension Object by adding columns to the existing report dataset, adding new data items,
adding to the request page, or adding a new layout.

Getting started
The following table includes links to help you get started with designing the reports.

TO SEE

Learn the overview of the report design process Report Design Overview

Understand the report structure and designing the layout Report Object
for a report.

Understand how to extend an existing report. Report Extension Object

Understanding the data model and dataset of a report Defining a Report Dataset

Learn how to create a report using a Word layout Creating a Word Layout Report

Learn how to create a report using an RDL layout report. Creating an RDL Layout Report

Learn about creating a report based on an Excel layout. Creating an Excel Layout Report
TO SEE

Learn how to create a report using a customer defined Creating a custom Layout Report
layout type.

Learn how to define multiple report layouts for one report. Defining Multiple Report Layouts

See Also
Report Object
Report Extension Object
Creating a Report
Request Pages
Creating an RDL Layout Report
Creating a Word Layout Report
Creating an Excel Layout Report
Defining Multiple Report Layouts
Utilizing Read Scale-Out for Better Performance
Report Design Overview
2/6/2023 • 2 minutes to read • Edit Online

A report is composed of the following items:


A report object
A report dataset
A report layout
A request page
Properties, triggers, and code
You design a report by first defining the dataset, and then designing the visual layout.

Report object
You create a report object in the AL Language development environment to define the data model, or dataset of
a report. You can structure and summarize information in a report and print documents, such as sales quotes
and invoices. For more information, see Report Object.
Report dataset
In order to define the underlying data model, you use the report dataset. A report dataset determines the data
that is extracted or calculated from the Dynamics 365 Business Central database tables that can be used in a
report. You build the report dataset by adding data items and columns. For more information, see Report
Dataset. You can also extend a dataset from an existing report, to add more columns for example. For more
information, see Report Extension Object.

TIP
It is possible to use a query object as the data source for a report. This can in many cases improve the performance of
data retrieval when running the report.

Report layouts
The visual layout determines the content and format of a report when it is viewed and printed. You build the
layout of a report by arranging data items and columns and specifying the general format, such as text font and
size. A report that is viewed, printed, or saved from a Dynamics 365 Business Central client must have a report
layout. There are three types of report layouts: layouts using report definition language (RDL), Word report
layouts, and Excel report layouts. You can also extend an existing report, for example, to add a new layout. For
more information, see Report Extension Object.

NOTE
The layout in a report extension will not automatically be used when the report extension is deployed. To use the report
extension layout, in Business Central, go to the Repor t Layout Selection page to choose to use the new layout for the
report in question by choosing it from the Custom Layout Description drop-down box.

RDL layout
To create an RDL layout report, you use Visual Studio Report Designer or Microsoft SQL Server Reporting
Services Report Builder. For more information, see Creating an RDL Layout Report.
IMPORTANT
RDL layouts can result in slower performance with document reports, regarding actions that are related to the user
interface (for example. like sending emails) compared to Word layouts. When developing layouts for document reports,
we recommend that you design Word layouts instead of RDL. With Word layouts, reports are not impacted by the
security constraints on sandbox app domains like they are with RDL layouts. From a service perspective, RDL layouts are
not trusted, so they will run in a sandbox app domain that only lives for the current report invocation.

Word report layout


You create Word layouts by using a Word Document. Word layouts are based on a Word document that
includes a custom XML parts that represents the report dataset. For more information, see Creating a Word
Layout Report.
Excel report layout
Excel report layouts are based on an Excel (.xlsx) document and can take advantage of the capabilities in Excel
such as sliders, diagrams, charts, pivot tables, and PowerQuery to design the report. For more information, see
Creating an Excel Layout Report.

See Also
Reports
Report Object
Report Extension Object
Report Data Type
Creating an RDL Layout Report
Creating a Word Layout Report
Request Pages
Report Object
2/6/2023 • 4 minutes to read • Edit Online

Reports are used to print or display information from a database. You can use a report to structure and
summarize information, and to print documents, such as sales quotes and invoices.
Creating a report consists of two primary tasks; the first task is to create the underlying data model and the next
is to define the visual layout that displays the data. The report object defines the underlying data model and
specifies which database tables and fields to pull data from. When the report is run, that data is displayed in a
specified layout; the visual layout, which determines the content and format of a report when it's viewed and
printed.
For more information about defining database tables and fields, see Defining a Report Dataset. For more
information about the Report data type, see Report Data Type.
You build the layout of a report by arranging data items and columns, and specifying the general format, such as
text font and size. There are three types of report layouts; client report definition, also called RDL layouts, Word
layouts, and Excel layouts. RDL layouts are defined in Visual Studio Report Designer or Microsoft SQL Server
Reporting Services Report Builder. Word layouts are created using Word. Word layouts are based on a Word
document that includes a custom XML part representing the report dataset. Excel layouts are created in Excel
based on the report dataset, utilizing the Excel capabilities such as sliders, diagrams, charts, pivot tables, and
PowerQuery. One report can contain multiple report layout definitions. For more information, see Defining
Multiple Report Layouts.
If you want to modify an existing report, for example, add new columns, add to the request page, or add a new
layout, you can create a report extension instead. For more information, see Report Extension Object.

TIP
It is possible to use a query object as the data source for a report. This can in many cases improve the performance of
data retrieval when running the report.

Snippet support
Typing the shortcut treport will create the basic layout for a report object when using the AL Language
extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Report example
The following example is a report that prints the list of customers. The report object defines a dataset of
columns from the Customer table. This example defines a report that uses an RDL report layout. For more
information about creating an RDL report layout, see Creating an RDL Layout Report. For more information on
creating a report that uses Word Layout, see Creating a Word Layout Report. For information about creating an
Excel layout, see Creating an Excel Layout Report.
report 50103 "Customer List"
{
CaptionML=ENU='Customer List';
DefaultLayout = RDLC; // if Word use WordLayout property
RDLCLayout = 'MyRDLReport.rdl';

dataset
{
dataitem(Customer;Customer)
{
RequestFilterFields="No.","Search Name","Customer Posting Group";
column(CompanyName;CompanyName)
{
}
column(CurrReport_PageNo;Customer."no.")
{
}
column(Customer_TableCaption_CustFilter;TableCaption + ': ' + CustFilter)
{
}
column(CustFilter;CustFilter)
{
}
column(Customer_No;"No.")
{
}
column(Customer_Customer_Posting_Group;"Customer Posting Group")
{
}
column(Customer_Customer_Disc_Group;"Customer Disc. Group")
{
}
column(Customer_Invoice_Disc_Code;"Invoice Disc. Code")
{
}
column(Customer_Customer_Price_Group;"Customer Price Group")
{
}
column(Customer_Fin_Charge_Terms_Code;"Fin. Charge Terms Code")
{
}
column(Customer_Payment_Terms_Code;"Payment Terms Code")
{
}
column(Customer_Salesperson_Code;"Salesperson Code")
{
}
column(Customer_Currency_Code;"Currency Code")
{
}
column(Customer_Credit_Limit_LCY;"Credit Limit (LCY)")
{
DecimalPlaces=0:0;
}
column(Customer_Balance_LCY;"Balance (LCY)")
{
}
column(CustAddr_1;CustAddr[1])
{
}
column(CustAddr_2;CustAddr[2])
{
}
column(CustAddr_3;CustAddr[3])
{
}
column(CustAddr_4;CustAddr[4])
{
}
}
column(CustAddr_5;CustAddr[5])
{
}
column(Customer_Contact;Contact)
{
}
column(Customer_Phone_No;"Phone No.")
{
}
column(CustAddr_6;CustAddr[6])
{
}
column(CustAddr_7;CustAddr[7])
{
}
column(Customer_ListCaption;Customer_ListCaptionLbl)
{
}
column(CurrReport_PageNoCaption;CurrReport_PageNoCaptionLbl)
{
}
column(Customer_NoCaption;FieldCaption("No."))
{
}
column(Customer_Customer_Posting_GroupCaption;Customer_Customer_Posting_GroupCaptionLbl)
{
}
column(Customer_Customer_Disc_GroupCaption;Customer_Customer_Disc_GroupCaptionLbl)
{
}
column(Customer_Invoice_Disc_CodeCaption;Customer_Invoice_Disc_CodeCaptionLbl)
{
}
column(Customer_Customer_Price_GroupCaption;Customer_Customer_Price_GroupCaptionLbl)
{
}
column(Customer_Fin_Charge_Terms_CodeCaption;FieldCaption("Fin. Charge Terms Code"))
{
}
column(Customer_Payment_Terms_CodeCaption;Customer_Payment_Terms_CodeCaptionLbl)
{
}
column(Customer_Salesperson_CodeCaption;FieldCaption("Salesperson Code"))
{
}
column(Customer_Currency_CodeCaption;Customer_Currency_CodeCaptionLbl)
{
}
column(Customer_Credit_Limit_LCYCaption;FieldCaption("Credit Limit (LCY)"))
{
}
column(Customer_Balance_LCYCaption;FieldCaption("Balance (LCY)"))
{
}
column(Customer_ContactCaption;FieldCaption(Contact))
{
}
column(Customer_Phone_NoCaption;FieldCaption("Phone No."))
{
}
column(Total_LCY_Caption;Total_LCY_CaptionLbl)
{
}

trigger OnAfterGetRecord();
begin
CalcFields("Balance (LCY)");
FormatAddr.FormatAddr(
CustAddr,Name,"Name 2",'',Address,"Address 2",
CustAddr,Name,"Name 2",'',Address,"Address 2",
City,"Post Code",County,"Country/Region Code");
end;

}
}

requestpage
{
SaveValues=true;
ContextSensitiveHelpPage = 'my-feature';
layout
{
}

actions
{
}
}

labels
{
LabelName = 'LabelText', Comment = 'Foo', MaxLength = 999, Locked = true;
}

trigger OnPreReport();
var
CaptionManagement : Codeunit 42;
begin
CustFilter := CaptionManagement.GetRecordFiltersWithCaptions(Customer);
end;

var
FormatAddr : Codeunit 365;
CustFilter : Text;
CustAddr : ARRAY [8] OF Text[50];
Customer_ListCaptionLbl : Label 'Customer - List';
CurrReport_PageNoCaptionLbl : Label 'Page';
Customer_Customer_Posting_GroupCaptionLbl : Label 'Customer Posting Group';
Customer_Customer_Disc_GroupCaptionLbl : Label 'Cust./Item Disc. Gr.';
Customer_Invoice_Disc_CodeCaptionLbl : Label 'Invoice Disc. Code';
Customer_Customer_Price_GroupCaptionLbl : Label 'Price Group Code';
Customer_Payment_Terms_CodeCaptionLbl : Label 'Payment Terms Code';
Customer_Currency_CodeCaptionLbl : Label 'Currency Code';
Total_LCY_CaptionLbl : Label 'Total (LCY)';
}

TIP
From the Business Central client, you can export report results as raw data to a Microsoft Excel file. The file contains all
columns of the dataset, but without the layout applied. Use the file to help validate that the report returns the expected
data, and to ensure that the report layout controls match the dataset value types. To export a report, run the report and
select the Send to > Microsoft Excel Document (data only) on the request page. For more information, see
Working with Reports - Send to Excel.

Schedule reports
It's possible to schedule a report to run at your desired date and time by using AllowScheduling property. By
setting the property to true, you'll get the Schedule action button to set the date and time for your report. To
learn more about scheduling a report, see AllowScheduling Property and Schedule a report.
See also
Report Extension Object
Request Pages
Report Properties
Creating an RDL Layout Report
Creating a Word Layout Report
Adding Help Links from Pages, Reports, and XMLports
Page Extension Object
Page Properties
Developing Extensions
AL Development Environment
Report Extension Example
2/6/2023 • 3 minutes to read • Edit Online

The following article illustrates how an existing table and report is extended by using extension objects. The
code snippets shown in this example don't provide a full end-to-end scenario that can be deployed; they're
intended to illustrate the way to extend existing functionality by using the Table Extension Object and Report
Extension Object.

The base table - BaseFoodTable


The report extension will be based on the following base table, which holds information about food and specific
details that applies to that. The Color field in this table is an enum, which is defined with the FoodColor enum
next.

table 50100 BaseFoodTable


{
DataClassification = ToBeClassified;
DataPerCompany = false;

fields
{
field(1; Name; Text[256]) { }
field(2; Color; Enum FoodColor) { }
field(3; Flavour; Text[256]) { }
field(4; "Vegan Friendly"; Boolean) { }
field(5; "Vegetarian Friendly"; Boolean) { }
field(7; Price; Decimal)
{
DecimalPlaces = 2;
}

field(8; Restaurant; Integer) { }


}

keys
{
key(PK; Name)
{
Clustered = true;
}
}
}

Defining an enum - FoodColor


The FoodColor enum enables selecting a descriptive color of an item in the BaseFoodTable .
enum 50100 FoodColor
{
Extensible = true;

value(0; White) { }
value(1; Red) { }
value(2; Black) { }
value(3; Brown) { }
value(4; Orange) { }
value(5; Green) { }
value(6; Blue) { }
}

The base report - FoodReport


The following FoodReportobject defines a report based on BaseFoodTable as a data source. There's a
DataItemLink to a second table that displays restaurant information. The report is defined with an RDL layout.
For more information, see Creating an RDL Layout Report.

report 50100 FoodReport


{
UsageCategory = Administration;
ApplicationArea = All;
DefaultLayout = RDLC;
RDLCLayout = 'FoodReport.rdl';
AllowScheduling = true;

dataset
{
dataitem(FoodTable; BaseFoodTable)
{
column(Name; Name) { }
column(Color; Color) { }
column(Flavour; Flavour) { }
column(Vegan_Friendly; "Vegan Friendly") { }
column(Vegetarian_Friendly; "Vegetarian Friendly") { }
column(Price; Price) { }
dataitem(Restaurant; Restaurant)
{
DataItemLink = ID = field(Restaurant);
column(RestaurantName; Name) { }
}

}
}
}

The table extension - GMOFood


In the next code snippet, the table extension GMOFood is defined. This table extension extends the BaseFoodTable
with extra fields to register more details about food. GMOFood adds a relation to the Producer table through the
ProducerID key.
tableextension 50200 GMOFood extends BaseFoodTable
{
fields
{
field(100; "GMO Free"; Boolean) { }
field(101; Organic; Boolean) { }

field(103; Calories; Decimal)


{
DecimalPlaces = 3;
}
field(102; ProducerID; Integer) { }
}
}

table 50202 Producer


{
DataPerCompany = false;
fields
{
field(1; ID; Integer) { }
field(2; Name; Text[256]) { }
}
}

The report extension - FoodExtension


As we've seen in the previous sections, the base table BaseFoodTable was extended with the GMOFood extension.
To reflect that change, it makes sense to extend the FoodReport to enable displaying the extra set of fields that
were added; both to the existing FoodTable and to the new table Producer . To do that, we need to use a report
extension object. For more information, see Report Extension Object. In the dataset element, three new
columns are added to the FoodTable dataitem, and a new dataitem element is introduced that adds columns
corresponding to the reports source table.

reportextension 50200 FoodExtension extends FoodReport


{
RDLCLayout = 'ExtendedFoodReport.rdl';

dataset
{
add(FoodTable)
{
column(GMO_Free; "GMO Free") { }
column(Organic; Organic) { }
column(Calories; Calories) { }
}

addfirst(Restaurant)
{
dataitem(Producer; Producer)
{
DataItemLink = ID = field(ProducerID);
DataItemLinkReference = FoodTable;
column(ProducerName; Name) { }
}
}
}
}

The example code above illustrates how additive changes to tables that are used on reports can use report
extension objects to reflect these changes.

See Also
Reports Overview
Report Object
Report Extension Object
Request Pages
OnPostReport (Report Extension) Trigger
OnPreReport (Report Extension) Trigger
OnAfterAfterGetRecord (Report Extension Data Set Modify) Trigger
OnAfterPostDataItem (Report Extension Data Set Modify) Trigger
OnAfterPreDataItem (Report Extension Data Set Modify) Trigger
OnBeforeAfterGetRecord (Report Extension Data Set Modify) Trigger
OnBeforePostDataItem (Report Extension Data Set Modify) Trigger
OnBeforePreDataItem (Report Extension Data Set Modify) Trigger
Defining a Report Dataset
2/6/2023 • 2 minutes to read • Edit Online

You use a report object in the AL Language development environment to define the data model, or dataset, of a
report. The dataset determines the data that is extracted or calculated from the Dynamics 365 Business Central
database tables that can be used in a report. For more information, see Report Object.

Using tables in a dataset definition


You build the report dataset from data items and columns. A data item is a table. A column can be:
A field in a table
A variable
An expression
A text constant
Typically, data items and columns correspond to fields in a table. When the report is run, each data item is
iterated for all records in the underlying table. Filters are applied and the dataset is created. When a report is
based on more than one table, you must set relations between the data items so that you can retrieve and
organize the data.
You can also extend a dataset from an existing report, to add more columns for example. For more information,
see Report Extension Object.

Using a query in a dataset definition


Instead of building the report dataset directly from tables, you can also use a query object. To achieve this, you
must
Add a global variable that points to the query object
Use an Integer in the data item definition
Add OnPreDataItem and OnAfterGetRecord triggers
See an example of how to do this below.

Snippet support
Typing the shortcut treport will create the basic layout for a report object when using the AL Language
extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Example: Using tables to define a report dataset


The following example adds the Customer table as the data item and the CustomerName and CompanyName as
fields of a column to the report. For more information on creating a report, see Creating a Word Report Layout.
dataset
{
dataitem(Customer; Customer)
{
column(CustomerName; CustomerName)
{
}
column(CompanyName; CompanyName)
{
}
}
}

TIP
From the Business Central client, you can export report results as raw data to a Microsoft Excel file. The file contains all
columns of the dataset, but without the layout applied. Use the file to help validate that the report returns the expected
data, and to ensure that the report layout controls match the dataset value types. To export a report, run the report and
select the Send to > Microsoft Excel Document (data only) on the request page. For more information, see
Working with Reports - Send to Excel.

Example: Using a query to define a report dataset


Let's imagine that you have created the query object CustomerQuery that joins the customer data with data from
some other table. The following example shows how you can use that query as the data source for a report
dataset.

// Example of how to use a query as the data source for a report dataset.
dataset
{
dataitem(Integer; Integer)
{
column(CustomerName; MyQuery.CustomerName)
{
}
column(SomeFieldFromAnotherTable; MyQuery.SomeFieldFromAnotherTable)
{
}

trigger OnPreDataItem()
begin
MyQuery.Open();
end;

trigger OnAfterGetRecord()
begin
if not MyQuery.Read() then
CurrReport.Break();
end;
}
}

var
MyQuery: Query "CustomerQuery";

See Also
Report Object
Report Extension Object
Reports Overview
Report Design Overview
Request Pages
2/6/2023 • 4 minutes to read • Edit Online

A request page is a page that is run before the report or XMLport starts to execute. Request pages enable end
users to specify options and filters for a report and an XMLport. Request pages are defined as part of designing
a Report object, a Report Extension Object, or an XMLport object. The syntax is shown further down in this
article. You design the filters on request pages by using the following report and XMLport properties:

P RO P ERT Y DESC RIP T IO N

RequestFilterHeading Property Sets a caption for the request page tab that is related to a
report's data item or an XMLport's table element.

RequestFilterHeadingML Property Sets the text used as a RequestFilterHeading Property for a


request page tab.

RequestFilterFields Property Specifies which columns are automatically included on the


tab of the request page that is related to a report's data
item or an XMLport's table element. The user can set filters
on these columns.

NOTE
Request pages for XMLports are not supported by the Business Central Web client in versions prior to Dynamics 365
Business Central 2019 release wave 2. If you try to run an XMLport with a Request page from the web client in these
versions, you receive an error that the XMLport page type is not supported. Alternatively, XMLport request pages do
work in the Dynamics NAV Client connected to Business Central.

By default, a request page is displayed, unless the UseRequestPage is set to false ; then the report or XMLport
will start to print as soon as it's run. In this case, end users can't cancel the report or XMLport run. It's still
possible to cancel the report or XMLport, but some pages may print.
By default, without having set anything else, a request page will always display the following buttons:
Send to
Print
Preview
Cancel
Additionally, you can add more options on the request page to allow the end user to filter the data displayed.

Filtering on request pages


The columns that you define as RequestFilterFields are shown on the request page and can be used for
filtering the data before viewing or printing the report.

NOTE
Only on the Windows client, filtering is possible even if RequestFilterFields is not set.
Defining the RequestFilterFields property in the dataitem() part of the report code is done as illustrated in
the following code example:

report 50103 "Customer List"


{
CaptionML = ENU = 'Customer List';
RDLCLayout = 'Customer List Report.rdl'; // if Word use WordLayout property
dataset
{
dataitem(Customer; Customer)
{
RequestFilterFields = "No.", "Search Name", "Customer Posting Group";
...

NOTE
It is recommended to add columns that the end-users of the report will frequently set filters on.

For more information about the report object, see Report Object.
Defining the RequestFilterFields property in the tableelement() part of an XMLport is done in a similar way:

XMLport 50104 "Export Customer List"


{
CaptionML = ENU = 'Export customer List';
Direction = Export;
schema
{
textelement(root)
{
XmlName = 'Root';
tableelement(Customer; Customer)
{
RequestFilterFields = "No.", "Search Name", "Customer Posting Group";
...

For more information about the XMLport object, see XMLport Object.
By default, for every data item in the report and table element in a XMLport, a FastTab for defining filters and
sorting is created on the request page. To remove a FastTab from a request page, don't define any
RequestFilterFields for the data item or table element and set the DataItemTableView property in a report or
the SourceTableView property in an XMLport to define sorting. The request page is displayed, but there's no tab
for this data item or table element.
If a DataItemTableView or SourceTableView isn't defined, then end-users can select a sort column and sort order
at runtime.
In a complex report or XMLport that uses data from several tables, the functionality may depend on a specific
key and sort order. Design your reports and XMLports so that end-users can't change the sort order in a way
that affects their functionality.
For data items and table elements whose source table contains calculated fields, such as amounts and quantities,
the Filter totals by: section is automatically included on the request page, which allows you to adjust various
dimensions that influence calculations.
TIP
For information about how to enter filter criteria on the request page, see Filtering in the Business Central application
help.

Defining a requestpage section


On reports, in addition to defining the filter options by setting the RequestFilterFields property, you can add a
requestpage section. In this section, you can set the SaveValues property to true in order to save the values
that the end user enters on the request page. When the report is run again, the end user will have the option to
use previously defined filters. You can also add a layout to the request page, specifying an Options section to
perform checks.

NOTE
You can use the SaveValues property together with the AllowScheduling property to set up the request page to
support multiple previews. When both properties are true , users can preview the report from the request page as
many times as the like, without having the request page close. This capability lets users change filters, see what the
generated report will look like, and then try again. If either property is set to false , the report won't support multiple
previews and the request page closes once the user previews the report. In this case, the request page includes a
Preview and Close button instead of Preview .

...
requestpage
{
SaveValues = true;

layout
{
area(content)
{
group(Options)
{
Caption = 'Options';
field(PostingDate; PostingDateReq)
{
ApplicationArea = Basic, Suite;
Caption = 'Posting Date';
ToolTip = 'Specifies the posting date for the invoice(s) that the batch job creates.
This field must be filled in.';
}
}
}
}

trigger OnOpenPage()
begin
if PostingDateReq = 0D then
PostingDateReq := WorkDate;
end;

var
PostingDateReq: Date;
}
...

See Also
Report Object
Report Extension Object
XMLport Object
Reports Overview
Report Design Overview
RunRequestPage Method
RequestFilterHeading Property
RequestFilterHeadingML Property
RequestFilterFields Property
DataItemTableView
Report Triggers and Runtime Operations
2/6/2023 • 8 minutes to read • Edit Online

This article describes the triggers and operations that are executed when a report is run. The triggers and
operations will depend on a few things, like:
Whether the report has request page
What action the user takes on the request page, like preview, print, and schedule
What preview mode the report uses
Some triggers are invoked in the report, while others are invoked on the request page. Understanding the
sequence of the triggers and operations will help you design reports that work as expected.

Overall report trigger and operations


For starters, look at the following diagram that illustrates the general overall flow when a report is invoked. The
flow is broken down even further in the next section, which discusses triggers and operations related to request
pages.
Current
Legacy

The following figure illustrates the general report trigger flow for Business Central version 20 and later.
When you start the report run, the OnInitReport Trigger is called. If the OnInitReport doesn't end the processing
of the report, then the request page for the report is run, if one is enabled. The page triggers for the request
page are called. On the request page, you select the options that you want for this report. You can also decide to
cancel the report run. If you decide to continue, then the OnPreReport Trigger is called. At this point, no data has
yet been processed. When the OnPreReport trigger has been run, the first data item is processed unless the
processing of the report was ended in the OnPreReport trigger.

TIP
For more information about the print triggers and operations, see Developing Printer Extensions in Business Central.

How data items are processed


Data items are processed one after the other, each in the same way. When there are no more data items, the
OnPostReport Trigger is called to do any necessary post processing, for example, removing temporary files.
The process for each data item is as follows:
1. Before the first record is retrieved, the OnPreDataItem Trigger is called.
2. Data item records are processed one at a time.
Processing a record involves executing the record triggers and outputting data. After a record is retrieved
from the data item, the OnAfterGetRecord (Data Items) Trigger is called.
If there's an indented data item, its records are also processed. After the last record in the indented data
item, the control returns to the point from which processing was started. In the case, it's the next record
of the data item on the next highest level.
3. After the last record has been processed, the OnPostDataItem Trigger is called.

Request page and preview triggers and operations


The section outlines the triggers and operations that are related to the report request page and report preview.
The following diagram illustrates the main trigger and operation sequence. The focus is on the triggers and
actions related to the request page invocation and button actions. See the sections that follow for details about
some of the concepts shown.
Request page preview modes
Request pages can invoke the preview window in two different modes: preview & close and multiple-preview .
The mode will affect the report behavior, depending on the trigger implementation in the current report. The
following table describes the two preview modes.
P REVIEW M O DE DESC RIP T IO N

preview & close The preview & close mode is the only mode supported in
Business Central 2020 release wave 1 (version 16) and
earlier. This mode invokes the preview action within the
current report instance, referred to as the primary instance.
In this mode, the request page closes when the user
previews the report. The user will then have to run the
report again if the preview doesn't show the expected result.

In the client, a request page that uses this mode will include
the Preview & Close button.

multiple-preview The multiple-preview mode was introduced in Business


Central 2020 release wave 1 (version 17.). It provides users
the ability to preview a report multiple times, without closing
the request page. When the preview action is selected, the
mode first captures the values in the visible request page
controls and filters. Then, it invokes a new report instance,
referred to as the child instance, to generate the preview
document based on the settings. The request page in the
original report instance will remain available after the user
closes the preview window.

In the client, a request page that uses this mode will include
the Preview button.

For more information to help your design, see Key Design Guidelines and Considerations.
How the mode is set
By default, reports use the multiple-preview mode. The mode is determined by two report properties:
SaveValues and AllowScheduling, as outlined in the following table:

SAVEVA L UES A L LO W SH EDUL IN G = T RUE A L LO W SH EDUL IN G = FA L SE

SaveValues = true Multiple-preview Preview & close

SaveValues = false Preview & close Preview & close

Visible and head-less request page flows


There are two different request page flows that can be invoked in the process: a visual request page and a head-
less request page. The request page flow used will depend on various design factors. Each type has a different
trigger sequence.
The visual request page flow is used on the request page instance that appears for the user in the client. In this
case, the triggers are executed on the primary instance.
The head-less request page flow shows the triggers that are executed when a report runs without a visible
request page. The head-less flow occurs under the following conditions:
In the child instance, when a report uses the multiple-preview mode
When a report is scheduled to run in the background
When a report is invoked with the request page XML data in the parameter list
When a report that doesn't have an enabled request page
The following diagram highlights the basic trigger sequence for a request page for the two possible request
pages.
The key differences between the two flows are the OnAfterGetCurrRecord and OnQueryClosePage triggers in
the visual flow. Only visible user interface elements are transferred to the child instances through the request
page XML data. User interaction triggers, like lookup, validate, and other page triggers, aren't invoked in head-
less reports flows.

NOTE
The GetPrinterName procedure in the diagram isn't an actual AL-enabled trigger. Instead, it's a call from platform to the
application code that subscribes to the GetPrinterName event, which will return the selected printer name for the current
report.

Detailed child instance triggers and operations in multiple -preview mode


With multiple-preview mode, a child instance is created off the parent visual request page. The child instance
collects data from visual request page, then uses the head-less request page to process data items and build the
PDF preview. The new instance will rerun most the report triggers and some request page triggers.
The following snippet lists the actual triggers that are invoked when a report is run. It starts from when the user
first selects preview, and continues through printing.
Lines prefixed with ROOT indicate triggers that are run in the primary instance.
Lines marked with --PAGE are triggers invoked from the request page. All other triggers originate from the
report object itself.
Lines prefixed with CHILD indicate triggers that are run in the child instance.
For simplicity, only one record in each nested data item is shown.
ROOT OnAfterSubstituteReport
ROOT OnInitReport
ROOT OnInit --PAGE
ROOT OnAfterHasCustomLayout
ROOT OnAfterGetPrinterName
ROOT OnOpenPage --PAGE
ROOT OnAfterGetCurrRecord --PAGE
CHILD OnInitReport --PAGE
CHILD OnInit --PAGE
CHILD OnOpenPage --PAGE
CHILD OnClosePage --PAGE
CHILD OnPreReport
CHILD OnAfterGetPaperTrayForReport
CHILD MasterRecord - OnPreDataItem
CHILD MasterRecord - OnAfterGetRecord 1
CHILD MasterRecordLines - OnPreDataItem
CHILD MasterRecordLines - OnAfterGetRecord 101
CHILD MasterRecordLines - OnPostDataItem
CHILD MasterRecord - OnPostDataItem
CHILD OnAfterHasCustomLayout
CHILD OnPostReport
CHILD OnMergeDocumentReport
ROOT OnQueryClosePage --PAGE
ROOT OnClosePage --PAGE
ROOT OnPreReport
ROOT OnAfterGetPaperTrayForReport
ROOT MasterRecord - OnPreDataItem
ROOT MasterRecord - OnAfterGetRecord 1
ROOT MasterRecordLines - OnPreDataItem
ROOT MasterRecordLines - OnAfterGetRecord 101
ROOT MasterRecordLines - OnPostDataItem
ROOT MasterRecord - OnPostDataItem
ROOT OnPostReport
ROOT OnMergeDocumentReport

Report layout flow


RDLC layouts
Word layouts

The following figure illustrates the flow associated with an RDLC report layout type.
Key design guidelines and considerations
Multiple -preview mode
Avoid the following implementations:
Set global variables in page triggers
Use the OnQueryClose page trigger to change global variables in the report
Depend on instance methods to be called to set state variables before report invocation
The request pages that have SaveValues property set to false .
If you have reports that use any of these implementations, refactor them to ensure report content
renders as expected.

NOTE
If a legacy report depends on global variable state, the developer can use a single instance codeunit to transfer
variable state between the two running instances. The state is the set in the primary object and read from the
child object.

For more information about the flow, see Request page and preview triggers and operations.
Only visible user interface elements are transferred to the preview in child instances.
User interaction triggers from the visible request page, like lookup, validate, and other page triggers,
aren't invoked in head-less request page flow in the child instance. Design these triggers so that they
don't affect variables that are hidden in the object. For more information, see Visible and head-less
request page flows.
OnInitRepor t trigger calls
OnInitRepor t trigger is run when the report initially invoked, and again for every preview of the report
in the child instance. This condition, in some cases, can mean that before the report is even executed, the
OnInitRepor t trigger has already run twice. For more information, see Detailed child instance triggers
and operations in multiple-preview mode.
The design of some reports may make it impossible or undesirable to run in the multiple-preview mode.
In these cases, the report should run in the preview & close mode. So as a developer, you set the
AllowScheduling property to false in the report object declaration. Optionally, you can set the
SaveValues property of request page to false , in which case, the mode will revert to preview & close
mode. However, this configuration isn't recommended, because it removes the ability to save current
settings for later use.
For more information, see Request Page Preview Modes.
General
Defining methods that have the same name in the report and table
If you have two methods with the same name, one defined in a report and the other in a table that is
referenced by the report, you cannot invoke the method defined in the report directly. By default, a call to
the method invokes the method that's defined in the table. This behavior occurs when the method is
called from a source expression or a trigger.

See Also
Report Triggers Report Data Item Triggers
Report Object
Triggers
Adding Pages and Reports to Tell me
2/6/2023 • 4 minutes to read • Edit Online

The Business Central client includes the Tell me feature that lets users find objects by entering search terms.
When you have added a page or a report in your extension, you most likely want it to be discoverable to users
in Tell me . In AL, you make a page or report searchable from Tell me by setting the UsageCategory property in
code. The UsageCategor y setting will make the page or report searchable, and the value chosen for the setting
will further sub categorize the item.
Tell me finds pages and reports by searching the captions that are specified on page and report objects by the
CaptionML property.

Working with the UsageCategory property


When you create a Page or a Report, you add the UsageCategory Property. If the UsageCategor y is set to
None , or if you do not specify UsageCategor y , the page or report will not show up when you search in
Dynamics 365 Business Central.

TIP
The UsageCategor y is also used to categorize pages and reports shown in the role explorer of the client. The role
explorer includes two actions: Repor ts and Analysis and Administration . Pages and reports set to
Repor tsAndAnalysis will show when the Repor ts and Analysis action is selected. Pages and reports set to
Administration will show when the Administration action is selected. For more information, see Finding Pages with
the Role Explorer.

UsageCategory property values


The values for the UsageCategor y property are listed below. The sub category will help the user navigate
through the search results and it is a best practice to be consistent when categorizing the pages and the reports
that you add. A consistent approach will help guiding the user and improve productivity.

VA L UE DESC RIP T IO N

None The page or report is not included in search.

Lists The page or report is listed as Lists under the Pages and
Tasks category.

Tasks The page or report is listed as Tasks under the Pages and
Tasks category.

ReportsAndAnalysis The page or report is listed as Repor ts and Analysis


under the Repor ts and Analysis category.

Documents The page or report is listed as Documents under the


Repor ts and Analysis category.

History The page or report is listed as Archive under the Repor ts


and Analysis category.

Administration The page or report is listed as Administration under the


Pages and Tasks category.

Adding additional search terms


You can specify other words or phrases that can help users find a page or report by using the
AdditionalSearchTerms and AdditionalSearchTermsML properties. If the page or report is searchable by Tell me
(that is, th UsageCategor y property is set a value other than None ), the search terms specified by these
properties are used in addition to the caption of the page or report. These properties are useful when the
caption does not always reflect what users will look for. A good example of this in Business Central is pages and
reports associated with Item . Users unfamiliar with Business Central might look for 'product' or 'merchandise'
instead of 'item'.
NOTE
For Business Central on-premises, the Business Central Web Server configuration file (navsettings.json) includes a setting
called UseAdditionalSearchTerms that enables or disables the use of additional search terms by the Tell me . For more
information, see Configuring Business Central Web Server Instances.

Example
The following example creates a SimpleItemList page and sets a UsageCategory property to the page, so that
the SimpleItemList page is discoverable through search using the Tell me feature. Also, the example sets the
AdditionalSearchTerms property to add two search terms for the page.

page 50210 SimpleItemList


{
PageType = List;
SourceTable = Item;
UsageCategory = Lists;
AccessByPermission = page SimpleItemList = X;
ApplicationArea = All;
AdditionalSearchTerms = 'product, merchandise';

layout
{
area(content)
{
group(General)
{
field("No.";"No.") {}
field(Name;Name) {}
field(Description;Description) {}
}
}
}
}

Optional settings
In addition to making a page or report searchable, you can control the access of an object by providing Read ,
Inser t , Modify , Delete , and Execute (RIMDX) permissions by adding the AccessByPermission property.
Likewise, control the application area access on the specified object by adding the ApplicationArea Property.
The AccessByPermission property and ApplicationArea property are the optional settings, which can be
applied with the UsageCategor y property. These settings are used to set restrictions on an object when you
enable the Search functionality.

Working in the Dynamics NAV Development Environment


NOTE
Dynamics NAV Development Environment is DISCONTINUED AFTER: Business Central Spring 2019.

If you are using the Dynamics NAV Development Environment, you can also set UsageCategor y ,
AdditionalSearchTerms , AccessByPermission , and ApplicationArea properties on pages and reports to
control their search.
After you change these properties by using the Dynamics NAV Development Environment, before the changes
take effect in the client, you must run Build Object Search Index from the Tools menu.

See Also
Adding Menus to the Navigation Pane
UsageCategory Property
Page Object
Report Object
AL Development Environment
Substituting Reports
2/6/2023 • 2 minutes to read • Edit Online

In versions prior to Business Central 2021 release wave 1 extensibility is not supported for report objects.
Therefore, if you want to make any changes to the dataset or the layout of a base application report, you must
create a new version of the report and apply the changes on the new object. Then you can override the base
report with your own customized version by subscribing to the OnAfterSubstituteRepor t event published by
Codeunit 44 – Repor tManagement . From Business Central 2021 release wave 1, report extensi

How to substitute a report for another report


To substitute a report, you create a method and subscribe it to the OnAfterSubstituteRepor t event, as shown
in the code below. The OnSubstituteReport method replaces the report specified by the ReportId with the one
given by the NewReportId parameter. In this example the "Customer - List" report will be substituted for
"My New Customer - List" .

codeunit 50100 "Substitute Report"


{
[EventSubscriber(ObjectType::Codeunit, Codeunit::ReportManagement, 'OnAfterSubstituteReport', '', false,
false)]
local procedure OnSubstituteReport(ReportId: Integer; var NewReportId: Integer)
begin
if ReportId = Report::"Customer - List" then
NewReportId := Report::"My New Customer - List";
end;
}

For more information on how to subscribe to events, see Subscribing to Events.


When the OnAfterSubstituteRepor t event is raised, the event subscriber method is called and the substitution
takes place.

NOTE
The event is called OnAfterSubstituteRepor t to match the pattern followed by other events in the
Repor tManagement codeunit, but the subscriber will be invoked before the substitution takes place.

The OnAfterSubstituteRepor t event is raised when:


1. The user activates a page action that runs the report to be substituted, that is, an action that has the
RunObject Property set to the report.
2. The report is invoked from the Tell Me window.
3. The report is called by one of the following static methods:
Run Method
RunModal Method
SaveAsHtml Method
SaveAsXml Method
SaveAsPdf Method
SaveAsExcel Method
SaveAsWord Method
RunRequestPage Method
Execute Method
Print Method
SaveAs Method
For more information about raising events, see Raising Events.

Good practices
Consider using the same caption for both reports, given by the Caption Property. Consequently, any links
and action captions that lead to the report will match the report itself. This is also relevant for bookmarks
linked to a report, since they maintain the caption of the original report, even if it has been substituted for
one with another caption.
Consider enhancing the code of the subscriber method to check if the report has already been replaced with
another extension. This is done by comparing the ReportId and NewReportId parameters before making the
change, such that if the value of the NewReportId parameter is different from the value of the ReportId
parameter and different from -1, it means that the report has already been substituted for another subscriber
of the OnAfterSubstituteRepor t event.

IMPORTANT
Make sure that if a report is called on code, you use a compatible report to replace it to avoid run time errors.

See Also
Report Data Type
Subscribing to Events
Events in AL
GetSubstituteReport Method
Get Started with AL
Testing Reports
2/6/2023 • 2 minutes to read • Edit Online

Testing your report requires you to run it and to verify the data output. This practice helps you ensure that your
customers are presented with complete and accurate data.
Before extensions, the output of a report was saved to a file, but extensions deployed to Dynamics 365 Business
Central cannot access the file system and therefore must save the output of a report to a stream. Codeunit
131007 Library - Report Dataset offers a high-level API for running and testing the output of reports that does
not require direct access to the file system.

Example
The following example shows how to initialize the codeunit 131007 Library - Report Dataset by using the
RunReportAndLoad method. This method is preferred as it will run the report and initialize the
Library - Report DataSet codeunit. To verify the output, call either the AssertElementWithValueExists or the
AssertElementWithValueNotExist method. The other methods in the library should work as well if they do not
contain “Tag” in the name. RUNREQUESTPAGE and [RequestPageHandler] are optional and you can use them when
you want to open the request page.

TIP
If you want to run the report separately and load the data from the input stream manually, you can use the
LoadDataFromInstream method.

codeunit 50105 MyReportTesting


{
Subtype = Test;

[Test]
[HandlerFunctions('RemittanceAdviceJournalRequestPageHandler')]
procedure TestingReports();
var
XmlParameters: Text;
LibraryReportDataset: Codeunit "Library - Report Dataset";
GenJournalLine: Record "Gen. Journal Line";
begin
// Run the Report Remittance Advice - Journal.
XmlParameters := Report.RunRequestPage(Report::"Remittance Advice - Journal");
LibraryReportDataset.RunReportAndLoad(Report::"Remittance Advice - Journal", GenJournalLine,
XmlParameters);

// Verifying Total Amount on Report.


LibraryReportDataset.AssertElementWithValueExists('Amt_GenJournalLine', GenJournalLine.Amount);
end;

[RequestPageHandler]
procedure RemittanceAdviceJournalRequestPageHandler(var RemittanceAdviceJournal: TestRequestPage 399);
begin
// Empty handler used to close the request page. We use default settings.
end;
}

Any changes done in the handler above will result in the XmlParameters being changed and applied
automatically when the report runs. Examples of the implementation in the existing tests are in Codeunit 133770
and Codeunit 134141 .

Remarks
TestRequestPage.SaveAsXML uses a different format than Report.SaveAsXML or Report.SaveAs by serializing the
output of Repor t Previewer . This is a component that will be deprecated in the future and replaced with the
new methods that can be used for the new tests. Another difference is that TestRequestPage.SaveAsXML requires
files to be saved to disk and loaded, while other methods work in memory, making them more efficient.

NOTE
The existing tests still need support and the codeunit solves this problem by supporting both formats for now.
TestRequestPage.SaveAsXML uses Tags for values, while the new format uses attributes. This means that you cannot use
any public method that contains "Tag" in the name to test the reports generated in the memory.

See Also
Reports Overview
Testing Pages
Test Codeunits and Test Methods
Creating a Word Layout Report
2/6/2023 • 3 minutes to read • Edit Online

When you create a new report, there are two main tasks. First, you define the report dataset of data items and
columns. Then, you design the report layout. These steps will show how to create a report based on a Word
layout. For more information about the report object, see Report Object and Report Extension Object.
Later in this article you can read more how to enable multiple report layouts. For more information, see
Enabling the Microsoft Word rendering engine.

Create a Word layout report


The following example extends the Customer List page with a trigger that runs the report as soon as the
Customer List page is opened.

NOTE
The Different first page and Different odd and even options for headers and footers in Word aren't supported for
HTML conversion. If you select either of these options, the header and footer won't appear in rendered output, such as an
Email Body.

1. Create a new extension to the Customer List page that contains code to run the report and a report
object by adding the following lines of code:

pageextension 50100 MyExtension extends "Customer List"


{
trigger OnOpenPage();
begin
report.Run(Report::MyWordReport);
end;
}

report 50124 MyWordReport


{
DefaultLayout = Word;
WordLayout = 'MyWordReport.docx';
}

2. Build the extension (Ctrl+Shift+B ) to generate the MyWordReport.docx file.


3. Add the Customer table as the data item and the Name field as a column to the report by adding the
following lines of code to the report. For more information about defining a dataset, see Report Dataset.
report 50124 MyWordReport
{
DefaultLayout = Word;
WordLayout = 'MyWordReport.docx';

dataset
{
dataitem(Customer; Customer)
{
column(Name; Name)
{

}
}
}
}

4. Build the extension (Ctrl+Shift+B ).


5. Open the generated report layout file in Word.
6. In Word, edit the layout using the XML Mapping Pane on the Developer tab.

NOTE
If you do not see the Developer tab, go to Options , then Customize Ribbon , and in the Main tabs section,
select the Developer check box.

7. In Word, to the right, in the Custom XML par t lookup, locate the report, and then open the layout.
8. Right-click on the Customer table, and in Inser t Content Control , select Repeating to add the
repeater data item.
9. Right-click on the Name field and in Inser t Content Control , select Plain Text to add the column as a
text box.
10. Save the report layout when you're done and then close it.
11. Back in Visual Studio Code, press Ctrl+F5 to compile and run the report.
You'll now see the generated report in preview mode.

NOTE
If the report layout is not generated, open the settings.json from Visual Studio Code. Use Ctrl+Shift+P , then
choose Preferences: Open User Settings , locate the AL Language extension . Under Compilation Options ,
choose Edit in settings.json and add the following line:

"al.compilationOptions": {
"generateReportLayout": true
}
TIP
From the Business Central client, you can export report results as raw data to a Microsoft Excel file. The file contains all
columns of the dataset, but without the layout applied. Use the file to help validate that the report returns the expected
data, and to ensure that the report layout controls match the dataset value types. To export a report, run the report and
select the Send to > Microsoft Excel Document (data only) on the request page. For more information, see
Working with Reports - Send to Excel.

Enabling the Microsoft Word rendering engine


APPLIES TO: Business Central 2022 release wave 1 and later

The rendering of Word reports is controlled by an application feature key. Enabling the key
RenderWordReportsInPlatform in the Feature Management page in Business Central will switch the Microsoft
Word report rendering to the new platform rendering, which supports multiple layouts and new triggers for
Save and Download actions.

NOTE
Application rendering is obsolete and will be deprecated in a future release. It is recommended to stay on the old platform
if you have extensions that use custom Word layouts and therefore cannot use the new platform, for example, because of
dependencies on the OnBeforeMergeDocument or OnBeforeMergeWordDocument events.

The following AL snippet can be used in code to implement rendering differentiation in extensions.

var
FeatureKey: Record "Feature Key";
PlatformRenderingInPlatformTxt: Label 'RenderWordReportsInPlatform', Locked = true;

// code snippet
if (FeatureKey.Get(PlatformRenderingInPlatformTxt) and (FeatureKey.Enabled = FeatureKey.Enabled::"All
Users")) then
// Platform rendering of Word reports, Custom layout types will be handled by the OnCustomDocumentMerger
event
....
else
// App rendering - The report type will be treated like a Word file and rendered by the application
...

For more information about feature management, see Enabling Upcoming Features Ahead of Time.

See Also
Setting up Hyperlinks in Word Report Layouts
Report Design Overview
Report Object
Report Extension Object
Developing a Custom Report Render
Creating an RDL Layout Report
Creating an Excel Layout Report
Creating an RDL Layout Report
2/6/2023 • 2 minutes to read • Edit Online

When you create a new report for Dynamics 365 Business Central, there are two things you have to consider;
defining the report dataset of data items and columns, and then designing the report layout. These steps will
show you how to create a very simple report based on an RDL layout. For more information about the report
object, see Report Object. And to learn how to extend an existing report, see Report Extension Object.

IMPORTANT
RDL layouts can result in slower performance with document reports, regarding actions that are related to the user
interface (for example. like sending emails) compared to Word layouts. When developing layouts for document reports,
we recommend that you design Word layouts instead of RDL. With Word layouts, reports are not impacted by the
security constraints on sandbox app domains like they are with RDL layouts. From a service perspective, RDL layouts are
not trusted, so they will run in a sandbox app domain that only lives for the current report invocation.

To create and modify RDL report layouts, you use SQL Server Report Builder or Microsoft RDLC Report
Designer. For information about required versions of these tools, see System Requirements.

Create an RDL layout report


To facilitate testing your report layout, the following simple example extends the Customer List page with a
trigger that runs the report as soon as the Customer List page is opened.
1. Create a new extension to the Customer List page that contains code to run the report, as well as a simple
report object by adding the following lines of code:

pageextension 50123 MyExtension extends "Customer List"


{
trigger OnOpenPage();
begin
report.Run(Report::MyRdlReport);
end;
}

report 50123 MyRdlReport


{
DefaultLayout = RDLC;
RDLCLayout = 'MyRDLReport.rdl';

2. Build the extension (Ctrl+Shift+B ) to generate the MyRDLReport.rdl file.


3. Add the Customer table as the data item and the Name field as a column to the report by adding the
following lines of code to the report:
report 50123 MyRdlReport
{
DefaultLayout = RDLC;
RDLCLayout = 'MyRDLReport.rdl';

dataset
{
dataitem(Customer; Customer)
{
column(Name; Name)
{
}
}
}
}

4. Build the extension (Ctrl+Shift+B ). The MyRDLReport.rdl file will be created in the root of the current
project.
5. Open the generated report layout file in Microsoft SQL Ser ver Repor t Builder .
6. Edit the layout by inserting a table.
7. Add the Name column from the Datasets folder into the table and save the .rdl file.
8. Back in Visual Studio Code, press Ctrl+F5 to compile and run the report in Dynamics 365 Business
Central.
You will now see the generated report in preview mode.

NOTE
If the report layout is not generated, open the settings.json from Visual Studio Code. Use Ctrl+Shift+P , then
choose Preferences: Open User Settings , locate the AL Language extension . Under Compilation Options ,
choose Edit in settings.json and add the following line:

"al.compilationOptions": {
"generateReportLayout": true
}

TIP
From the Business Central client, you can export report results as raw data to a Microsoft Excel file. The file contains all
columns of the dataset, but without the layout applied. Use the file to help validate that the report returns the expected
data, and to ensure that the report layout controls match the dataset value types. To export a report, run the report and
select the Send to > Microsoft Excel Document (data only) on the request page. For more information, see
Working with Reports - Send to Excel.

See Also
Report Design Overview
Report Object
Creating a Word Layout Report
Creating an Excel Layout Report
Defining Multiple Report Layouts
Creating an Excel Layout Report
2/6/2023 • 3 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 1 and later

When you create a new report, there are two main tasks to consider. First, you define the report dataset of data
items and columns. Then, you design the report layout. With the Excel report layout, you can create a basic
report that prints a dataset and leave it up to the end-user to further modify it by using the full palette of
capabilities in Excel such as sliders, diagrams, charts, pivot tables, and PowerQuery to design the report. This
offers flexibility and freedom for the end-user, being able to change the look and feel of a report, adding
additional views, filtering, and sorting on data. Such a layout designed by the end-user, can be imported and
used as a new layout. The following steps will show how to create a basic report based on an Excel layout.
The example illustrates how compilation triggers a starter template for the Excel layout. If an existing layout is
referenced with the LayoutFile property the layout is validated based on the schema of the report dataset.
For more information about the report object, see Report Object and for report extension objects, see Report
Extension Object.

Create a simple Excel layout report


The following example extends the Contact List report only by adding a rendering section, which adds a new
Excel layout to the list of options for printing the Contact List report. The layout does not yet exist, but will be
generated based on the existing report dataset for the report and can then be modeled by using Excel reporting
capabilities. The example uses the Type Property to set the type of report to Excel and it uses the LayoutFile
Property to specify the name of the file that contains the Excel layout. If this is not present, it will be generated.
1. Create a new report extension of the Contact List page by adding the following lines of code:

reportextension 50101 MyExtContactList extends "Contact - List"


{
rendering
{
layout(LayoutExcel)
{
Type = Excel;
LayoutFile = 'MyExcelContactList.xlsx';
}
}
}

2. Now, press Ctrl+Shift+P , and then choose AL: Package . The MyExcelContactList.xlsx will be
generated, as you can see in the right pane of Visual Studio Code.

TIP
Another way of generating the data set to build a layout on, is to run a report in Business Central and on the
request page, then choose the Microsoft Excel Document (data only) option, and you will get the same
starting point. Then you can design the layout, save as a new layout, and include in your AL project.

3. Right-click the generated MyExcelContactList.xlsx file, and choose Reveal in File Explorer . This will
open File Explorer.
4. Choose the MyExcelContactList.xlsx file in File Explorer and open it in Excel.
Excel now opens and you should see the dataset of the Contact List. Note that it is important to not
change the dataset in Excel, only the layout.
5. In Excel, go to the Inser t tab, choose PivotTable , and then choose From Table/Range with the default
options of Data and New worksheet . Choose the OK button.
6. From the PivotTable Fields pane to the right, choose a suitable number of fields to add to the report.
7. Save the report and close the Excel window.
8. Back in Visual Studio Code, press Ctrl+F5 to compile and launch Business Central.
9. Now, to choose the changed report layout, search for the Repor t Layout Selection page, and then
search for the Contact List (ID 5050) report.
10. In the Layout Type column, choose Excel , and then choose the Run Repor t from the action bar.
11. On the request page, choose the Download button, and once the report is downloaded, open it.
12. In Excel, you should now see the Contact List report as a pivot table, sorted as you specified in step 6.

NOTE
If the report layout is not generated, open the settings.json from Visual Studio Code. Use Ctrl+Shift+P , then
choose Preferences: Open User Settings , locate the AL Language extension . Under Compilation Options ,
choose Edit in settings.json and add the following line:

"al.compilationOptions": {
"generateReportLayout": true
}

It is possible to specify multiple layouts for a report. For more information, see Defining Multiple Report
Layouts.

See also
Report Design Overview
Report Object
Creating a Word Layout Report
Creating an RDL Layout Report
Defining Multiple Report Layouts
ExcelLayout Property
LayoutFile Property
Defining Multiple Report Layouts
2/6/2023 • 2 minutes to read • Edit Online

In AL you have the option of defining multiple layouts for one report in code. This means that you can offer
multiple versions of a layout for different purposes. Defining multiple layouts applies to both report objects, and
report extension objects. The layouts can be of different types, meaning that you can have, for example, a Word
layout and an Excel layout for one report, or multiple Excel layouts for one report. This enables creating report
extensions that only add layouts to an existing report and packaging it as an extension .al file.
Read more about enabling multiple report layouts and implementing rendering differentiation in extensions, see
Enabling the Microsoft Word rendering engine.

Enabling multiple layouts


To enable multiple layouts, you must use the rendering section of a report object. Inside the rendering section,
you define one or more layout sections. In each of the layout sections, you specify details about the layout file
path and name, you provide a Caption Property and a Summary Property which will be displayed to the user in
the Repor t Layouts page in Business Central.
The default layout can be specified with the DefaultRenderingLayout Property report property. This property
cannot be set on report extension objects, only on report objects.

NOTE
If you do not specify a caption, the layout name will be displayed to the user.

If the extension is translated, the Caption and Summary properties are included in the .xliff file and translated as
well. For more information, see Working with Translation Files.

TIP
Reports using the previous property-based layout specification can be converted to use the rendering section by using
a code action. To use this, ensure code that actions are switched on in your AL extension settings and place the cursor on
any of the old layout properties to use the action. Layouts of type RDLC, Word, Excel, and Custom can be specified with
the new rendering syntax. For more information, see AL Language Extension Configuration.

Layout definition in AL
The following example illustrates how the EmpReportExt report extends the "Employee - List" list by adding
four report layouts as options for printing this report. The report extension only adds the layouts, the dataset
remains the same as the existing Employee List report.
reportextension 50102 EmpReportExt extends "Employee - List"
{
rendering
{
layout(LayoutExcelPivot)
{

Type = Excel;
Caption = 'ExcelPivot';
Summary = 'Employee list shown in Pivot table in Excel';
LayoutFile = 'EmpShownAsPivot.xlsx';
}

layout(LayoutExcel)
{
Type = Excel;
Caption = 'ExcelColumns';
Summary = 'Employee list sorted by last name in Excel';
LayoutFile = 'EmpSortedByLastName.xlsx';
}

layout(LayoutWord)
{
Type = Word;
Caption = 'WordList';
Summary = 'Employee list sorted by last name in Word';
LayoutFile = 'EmpSortedByLastName.docx';
}
}
}

If one or more of the layouts do not exist, they will be generated when pressing Ctrl+Shift+P , and then
choosing AL: Package . The layouts will appear in your project in the right pane of Visual Studio Code. The
generated reports contain the dataset from the report, and you can modify and model the reports in each of the
layout types as you want.
Creating layouts in Excel, RDL, or Word is further described in the topics shown under See also.

See also
Creating an Excel Layout Report
Creating an RDL Layout Report
Creating a Word Layout Report
Developing a Custom Report Render
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 1 and later

This article describes the concept of a custom report render. The custom report render manages the rendering
of a generated report dataset with a layout type specified by an extension. The actual rendering will take place in
the application by using the OnCustomDocumentMergerEx event provided by the ReportManagement codeunit. The
layout must be specified in the rendering section in the report definition.

History and context


The custom render feature is a substitute for the business events that were used in the OnDocumentMerge event
provided by the DocumentManagement codeunit for rendering Word documents in the application. When using the
custom render logic, the report can support multiple layouts and the event code won't have dependencies to
standard Word layout processing in the platform or application. The layout files that are provided in the
extension are imported without any further processing, whereas the Word documents are aligned with the
platform requirements for that format.

Layout declaration for a custom render


report 50000 "Standard Report Layout"
{
DefaultRenderingLayout = CustomLayout;
...
rendering
{
layout(CustomLayout)
{
Type = Custom;
LayoutFile = './StandardReportLayout.custom';
Caption = 'First custom layout';
Summary = 'First custom layout summary';
MimeType = 'Application/Report/MyExtension';
}
}
}

Sample AL code
The simplest possible custom document render can be implemented as in the following sample. The example
will use the existing application logic to render XML datasets into Microsoft Word or PDF documents using a
given template (Word template).

[EventSubscriber(ObjectType::Codeunit, Codeunit::ReportManagement, 'OnCustomDocumentMergerEx', '', true,


true)]
local procedure OnCustomDocumentMergerEx(ObjectID: Integer; ReportAction: Option
SaveAsPdf,SaveAsWord,SaveAsExcel,Preview,Print,SaveAsHtml; ObjectPayload: JsonObject; XmlData: InStream;
LayoutData: InStream; var DocumentStream: OutStream; var IsHandled: Boolean)
var
DocumentReportMgt: Codeunit "Document Report Mgt.";
TempBlob: Codeunit "Temp Blob";
DataInStream: InStream;
DataOutStream: OutStream;
ObjectName: JsonToken;
DocumentTypeParts: List of [Text];
DocumentType: JsonToken;
Extension: Text;
Token: JsonToken;
MimeType: Text;
LayoutName: Text;
LayoutModel: Text;
JsonText: Text;
JsonFile: File;
begin
if IsHandled then
exit;

Init();

// Sample code to persist the json object to disk


ObjectPayload.WriteTo(JsonText);
JsonFile.TextMode := true;
JsonFile.Create(TempFolderPath + 'OnCustomDocumentMergerEx.json', TextEncoding::UTF8);
JsonFile.Write(JsonText);
JsonFile.Close();

// Get report options from the json object


ObjectPayload.Get('objectname', ObjectName);
ObjectPayload.Get('documenttype', DocumentType);
ObjectPayload.Get('layoutmimetype', Token);
MimeType := Token.AsValue().AsText();

ObjectPayload.Get('layoutname', Token);
LayoutName := Token.AsValue().AsText();

ObjectPayload.Get('layoutmodel', Token);
LayoutModel := Token.AsValue().AsText();

DocumentTypeParts := DocumentType.AsValue().AsText().Split('/');

// Notice that the Extension below have to be remapped to a standard file extension based on the
document mimetype.
Extension := DocumentTypeParts.Get(DocumentTypeParts.Count);

TempBlob.CreateOutStream(DataOutStream);

// The
case ReportAction of
ReportAction::SaveAsPdf, ReportAction::Preview, ReportAction::Print:
begin
if not DocumentReportMgt.TryXmlMergeWordDocument(LayoutData, XmlData, DataOutStream)
then
error('Unable to handle custom document merge');
DocumentReportMgt.ConvertWordToPdf(TempBlob, ObjectID);
TempBlob.CreateInStream(DataInStream);
CopyStream(DocumentStream, DataInStream);
IsHandled := true;
end;
ReportAction::SaveAsHtml:
begin
if not DocumentReportMgt.TryXmlMergeWordDocument(LayoutData, XmlData, DataOutStream)
then
error('Unable to handle custom document merge');
DocumentReportMgt.ConvertWordToHtml(TempBlob);
TempBlob.CreateInStream(DataInStream);
CopyStream(DocumentStream, DataInStream);
IsHandled := true;
end;
ReportAction::SaveAsWord:
begin
if not DocumentReportMgt.TryXmlMergeWordDocument(LayoutData, XmlData, DocumentStream)
if not DocumentReportMgt.TryXmlMergeWordDocument(LayoutData, XmlData, DocumentStream)
then
error('Unable to handle custom document merge');
IsHandled := true;
end;
else
error('Unsupported report action %0', ReportAction);
end;
end;

See Also
Working With and Troubleshooting Payloads
OnCustomDocumentMergerEx Event
Events in AL
Publishing Events
Raising Events
Subscribing to Events
Walkthrough: Designing a Report from Multiple
Tables
2/6/2023 • 22 minutes to read • Edit Online

A report object is composed of a report dataset and a visual layout. You design a report by first defining the
dataset and then designing the visual layout. You define the dataset for reports directly in AL code. You can
design the layout in Visual Studio Report Designer or Microsoft SQL Server Reporting Services Report Builder
for an RDL layout, in Microsoft Word for a Word layout, and in Microsoft Excel for an Excel layout. After you
design a report, you can make it available to applications that are running on the Business Central Web client. A
report can be designed from one table or multiple tables. This walkthrough demonstrates how to design a
report from multiple tables.

About This Walkthrough


This walkthrough shows you how to design a report from the AL Language development environment and
using Visual Studio Report Designer for designing an RDL layout.
This walkthrough illustrates the following tasks:
Defining the dataset for multiple tables.
Adding fields to a data item.
Defining properties for the data items.
Adding labels to a report.
Design a client report definition (RDL) report layout in Visual Studio 2019.
Setting filters to hide empty rows and fields in a report.
Building and running a report.

Story
Viktor is a developer who is working for CRONUS International Ltd. Viktor has been asked by his manager to
create a report that shows data from the Customer (ID 18), Cust. Ledger Entry (ID 21),
Detailed Cust. Ledger Entry (ID 379), and the Sales Header (ID 36) tables. The report should meet the
following requirements:
The report must display customer information at the top of the report.
For each customer, the report must show a list of ledger entries.
For each ledger entry, the report must show a list of detailed ledger entries under the ledger entries.
The report must display basic sales document headers information for the selected customer.
Each section of the data for each customer must begin on a new page.
The Amount field from the Cust. Ledger Entry table should be totaled and displayed for each customer.
If there are no records to display, the report must not display that data sections. For example, if there are
no sales documents for a customer, the sale header section must be skipped.
Amount fields must not display zero values.
The orientation of the report should be landscape.
The following illustration shows an example of the second page of the report.

Defining the Dataset


Viktor starts by creating an empty report object by using the AL Language extension in Visual Studio Code. You
can use the shortcut treport to create the basic layout for a report object.
He sets the DefaultLayout Property to RDLC to specify that he'll use an RDL layout for the report and the
RDLCLayout Property to 'MyRDLReport.rdl' , the name of the rdl file he'll use for the layout.
Viktor will now design the dataset to display customers and their transaction details. This is defined within the
dataset part of the report object.

Adding Data Items and columns


The datasets for the data model will come from four tables: Customer , Cust. Ledger Entry ,
Detailed Cust. Ledger Entry , and Sales Header . Viktor will create a data item for each table with the dataitem
control. Moreover, for each table, he'll add the fields that he wants to display on the report. Each field is given by
a column control, defined inside the corresponding data item.
The hierarchy of the dataitem and column controls is important because it will determine the sequence in
which data items are linked, which in turn will control the results. Working from top-to-bottom, you start by
adding the dataitem control for first table that you want in the dataset, then add column controls for each table
field that you want to include in the dataset. For the next table, you add another dataitem control that is
embedded within the first dataitem control, then add column controls as needed. You continue this pattern for
more tables and fields.
Defining Properties for the Data Items
Once, Viktor has specified the data item and column elements he'll define the appropriate properties. He sets the
DataItemTableView Property in each data item to sort the table view based on a specific field.
He also sets the RequestFilterFields Property to automatically include a specific field on the filter tab of the
request page. For more information about request pages, see Request Pages.
Now, Viktor uses the DataItemLink (Reports) Property to set a link between one or more fields of the data item
tables. Links determine which records to include in the dataset based on the values of a common field between
data items. This property must be set on the lower data item of the report object.
For each of the column controls he adds the IncludeCaption Property and sets it to True . This property specifies
to include the caption of the fields in the dataset of a report.
Finally, he sets the PrintOnlyIfDetail Property to True on a data item to print data only if at least one of its child
data items generates output.
Adding Labels to the Report
Viktor will now add labels to the report. You define the labels in the label part of the report. These labels will
be used later as captions.
The following code exemplifies the code that Viktor has written for the report.

report 50101 "Report for Multiple Tables"


{
//Make the report searchable from Tell me under the Administration category.
UsageCategory = Administration;
ApplicationArea = All;
// Use an RDL layout.
DefaultLayout = RDLC;
// Specify the name of the file that the report will use for the layout.
RDLCLayout = 'MyRDLReport.rdl';

dataset
{

dataitem(Customer; Customer)
{
// Sort the table view based on the "No." field.
DataItemTableView = Sorting("No.");
// Include the "No." field on the filter tab of the request page.
RequestFilterFields = "No.";
// Print data only if at least one of the CustLedgerEntry and SalesHeader data items generates
output.
PrintOnlyIfDetail = True;

// For each field that you want to display you add a column control.
column(No_Customer; "No.")
{
// Include the caption of the "No." field in the dataset of the report.
IncludeCaption = true;
}

column(Name_Customer; Name)
{
IncludeCaption = true;

column(Phone_Customer; "Phone No.")


{
IncludeCaption = true;

column(Address_Customer; Address)
{
IncludeCaption = true;

column(EMail_Customer; "E-Mail")
{
IncludeCaption = true;

}
dataitem(CustLedger; "Cust. Ledger Entry")
{

DataItemTableView = sorting("Entry no.");


// Set a filter on the child data item, **CustLedgerEntry** to select only the records where
the
// value of `Customer."No."` field and the `"Customer Ledger Entry"."Customer No."` field
matches.
DataItemLink = "Customer No." = field("No.");

column(EntryNo_CustLedgerEntry; "Entry No.")


{
IncludeCaption = true;

}
column(CustomerNo_CustLedgerEntry; "Customer No.")
{
IncludeCaption = true;

}
column(PostingDate_CustLedgerEntry; "Posting Date")
{
IncludeCaption = true;

}
column(DocumentType_CustLedgerEntry; "Document Type")
{
IncludeCaption = true;

column(DocumentNo_CustLedgerEntry; "Document No.")


{
IncludeCaption = true;

column(Description_CustLedgerEntry; Description)
{
IncludeCaption = true;

column(CurrencyCode_CustLedgerEntry; "Currency Code")


{
IncludeCaption = true;

column(Amount_CustLedgerEntry; Amount)
{
IncludeCaption = true;

column(OriginalAmtLCY_CustLedgerEntry; "Original Amt. (LCY)")


{
IncludeCaption = true;

column(RemainingAmtLCY_CustLedgEntry; "Remaining Amt. (LCY)")


{
IncludeCaption = true;

dataitem(DetCustLedger; "Detailed Cust. Ledg. Entry")


{

DataItemTableView = sorting("entry no.");


DataItemLink = "Cust. Ledger Entry No." = field("Entry No."), "Customer No." =
field("Customer No.");

column(EntryNo_DetailedCustLedgEntry; "Entry No.")


column(EntryNo_DetailedCustLedgEntry; "Entry No.")
{
IncludeCaption = true;

column(EntryType_DetailedCustLedgEntry; "Entry Type")


{
IncludeCaption = true;

column(PostingDate_DetailedCustLedgEntry; "Posting Date")


{
IncludeCaption = true;

column(DocumentType_DetailedCustLedgEntry; "Document Type")


{
IncludeCaption = true;

column(DocumentNo_DetailedCustLedgEntry; "Document No.")


{
IncludeCaption = true;

column(AmountLCY_DetailedCustLedgEntry; "Amount (LCY)")


{
IncludeCaption = true;

column(TransactionNo_DetailedCustLedgEntry; "Transaction No.")


{
IncludeCaption = true;

column(JournalBatchName_DetailedCustLedgEntry; "Journal Batch Name")


{
IncludeCaption = true;

column(DebitAmountLCY_DetailedCustLedgEntry; "Debit Amount (LCY)")


{
IncludeCaption = true;

column(CreditAmountLCY_DetailedCustLedgEntry; "Credit Amount (LCY)")


{
IncludeCaption = true;

}
}

dataitem(SalesHeader; "Sales Header")


{
DataItemTableView = sorting("Document Type", "No.");
DataItemLink = "Sell-to Customer No." = field("No.");

column(DocumentType_SalesHeader; "Document Type")


{
{
IncludeCaption = true;

column(No_SalesHeader; "No.")
{
IncludeCaption = true;

column(PostingDate_SalesHeader; "Posting Date")


{
IncludeCaption = true;

column(PricesIncludingVAT_SalesHeader; "Prices Including VAT")


{
IncludeCaption = true;

column(Amount_SalesHeader; Amount)
{
IncludeCaption = true;

}
}

}
}

// These labels will be used later as captions in the report layout.


labels
{
Sales_Document_Caption = 'Sales Documents';
Total_Caption = 'Total';
}
}

Designing the visual RDL layout for the report


Next, Viktor will design an RDL layout for the report by using Visual Studio Report Designer. He'll set properties
for the report and the report elements, format the report, and then add the data to the report.
To design the RDL layout for the report
1. Build the extension (Ctrl+Shift+B) to generate the MyRDLReport.rdl file, and then open the file with Visual
Studio 2019.
2. Right-click anywhere outside the report (in the shaded area) and then choose Add Page Header .
3. Right-click anywhere outside the report (in the shaded area), and then choose Repor t Proper ties .
4. In the Repor t Proper ties window, choose the Page Setup tab. In the Paper size section, under
Orientation , choose Landscape , and then choose the OK button.
5. On the View menu, choose Toolbox . Select the List control, and then choose the body of the report to
add the List control to the report. This control will contain and group all the data.
6. Move the List control to the top of the report body and resize it to cover the whole report body.
7. Right-click the middle of the List controls, and then select on the box to open the Rectangle Proper ties .
8. In the Rectangle Proper ties window, choose the Fill tab, in the Fill Color list color pallet, select
Cornflower Blue from the color pallet, and then choose the OK button. You can choose any color.

NOTE
Changing the color of report elements helps you identify elements on the report preview. You can set different
color properties for table header, detail rows, text boxes, and so on.

Viktor will set the properties of the List control to hold the dataset, group the data by Customer No. and
set up how the groups should be displayed.
To set the list control properties
1. Select the List control, right-click the shaded border to the left of the List control, and then choose Tablix
Proper ties .
2. In the Tablix Proper ties window, on the General tab, under Dataset name , select DataSet_Result
from the drop-down list, and then choose the OK button.
3. Select the List control, right-click the shaded border to the left of the list control, choose Row Group ,
and then Group Proper ties .
4. In the Group Proper ties window, on the General tab, under Group expressions:, choose the Add
button, and then select [No_Customer] from the Group on: drop-down list. This groups all the data in
the List control by customer number.
5. On the Page Breaks tab, select Between each instance of a group , and then choose the OK button.
Viktor is now ready to add the customer data. The table will display one customer at a time, therefore Viktor
must put all the fields into table header rows. The table data and footer rows will be disabled.
To add customer data
1. From the Toolbox pane, drag a Table control into the List control and resize the table to about the half
the width of the list control. This table will contain the customer data.
The following illustration shows the list control and the table.

The table contains two table rows, a header row (first row), and a data row (second row). The three
parallel lines in the left border of the second row identify the data row.
2. Select any table row, right-click the shaded border, and then choose Tablix Proper ties to open the
Tablix Proper ties window.
3. On the General tab, verify that the Dataset name field is set to DataSet_Result , and then choose the
OK button.
The table has three columns. Viktor will add a fourth column to the table to hold all the customer data.
4. Right-click the middle column header, choose Inser t Column , and then select Right to insert the fourth
column into the table.
5. Select the second table row (the data row), right-click the row, choose Delete Rows to delete the data
row, and then choose the OK button in the Delete Rows window to delete the row and its associated
groups.
6. Select the remaining table row, right-click the shaded border on the left, choose Inser t Row , and then
choose Below to insert another table header row.
7. Repeat step 6 to insert a third table header row. There should now be three header rows in the table.
8. Right-click the first cell (row 1, column 1) in the table, and then choose Expression to open the
Expression window.
9. In the Categor y column, select Parameters , in the Item column, verify that All is selected, and then in
the Values column, double-click No_CustomerCaption . Verify that the Set expression for : Value box
contains the following value: =Parameters!No_CustomerCaption.Value . This cell will display the customer
No. caption in the report.
10. Modify the expression to =First(Parameters!No_CustomerCaption.Value) . Choose the OK button.

NOTE
All caption fields must begin with =First so that the first value for the caption fields in the data set is retrieved
and used as caption. If the First function is not used, the report will return the current value for a field. The current
value however may be incorrect. For example, the current value could be empty.

11. Right-click the second cell (row 1, column 2) in the table, and then choose Expression to open the
Expression window.
12. In the Categor y column, select Field(DataSet_Result) , in the Item column verify that All is selected,
and then in the Values column double-click No_Customer . Verify that the Set expression for : Value
box contains the following value =Fields!No_Customer.Value . Choose the OK button. This cell will display
the Customer No..
13. Repeat steps 8 through 12 to the enter captions and values in the following cells.

NOTE
Columns 1 and 3 will contain the captions and columns 2 and 4 will contain the values.

RO W C O L UM N C A P T IO N VA L UE

2 1 Name_CustomerCaption None

2 2 None Name_Customer

1 3 Address_CustomerCaptio None
n

1 4 None Address_Customer

2 3 PhoneNo_CustomerCapti None
on

2 4 None PhoneNo_Customer

3 3 Email_CustomerCaption None
RO W C O L UM N C A P T IO N VA L UE

3 4 None Email_Customer

14. Select all table rows (not the whole table), and then on the View menu, choose Proper ties Window to
open the Proper ties window in Visual Studio.
15. In the Proper ties window, under Fill , set the BackgroundColor property to Plum . You can choose any
color.
The layout that Viktor has designed to this point resembles the following illustration.

16. On the Build menu, choose Build Web site to build the project. Inspect the Output pane and make sure
that there are no build errors. Close Visual Studio.

NOTE
It is a good practice to build the project periodically during the report design to make sure that there are no build
errors.

Viktor will run the report and preview what he's done to this point.
17. Go back to your project in Visual Studio Code and Reload the Window.
18. In the launch.jsonfile set the "startupObjectId" to the Id of the report object and the
"startupObjectType" to Report .

19. Press the F5 key to run the report.


20. In the request page that is displayed, choose the Preview button to view the report. The first customer is
displayed on the first page. If you page through the report, each customer is displayed on a separate
page.
Viktor will now add the data for the customer ledger entries and detailed ledger entries. The entries will be put
in a different table.
To add the data for ledger entry and detailed ledger entry
1. Open the MyRDLReport.rdl report in Microsoft Visual Studio.
2. From the Toolbox , drag a table control into the list control. Put the table under the table that contains the
customer data.

NOTE
You may have to resize the report body and the list controls to make them larger.

3. Select the table, right-click the shaded border, choose Tablix Proper ties . On the General tab, verify that
the Dataset name field is set to DataSet_Result , and then choose the OK button.
4. Select the table data row, choose Inser t Row and then choose Outside Group – Below . This adds
another data row to the table. You now have one header row and two data rows.
5. Delete the first row (header row) in the table and then insert columns in the table so that the total
number of columns is 11.
6. Choose the first data row, right-click the shaded border to the left, choose Add Group , and then choose
Parent Group .
7. In the Tablix group window, select Group by , select Entr yNo_CustLedgerEntr y from the drop-down
list. Select Add group header , and then choose the OK button.
8. Right-click the first row, choose Inser t Row , and then choose Inside Group – Above . This header will
hold the captions for the Customer Ledger entries.
9. Right-click the cell in the row1, column 2, and then choose Expression to open the Expression window.
10. In the Categor y column, select Parameters and then in the Values column double-click
Entr yNo_CustLedgerEntr yCaption . The Set expression for : Value box contains the following value:
=Parameters!EntryNo_CustLedgerEntryCaption.Value

11. Modify the expression to the following value: =First(Parameters!EntryNo_CustLedgerEntryCaption.Value) .


12. Repeat steps 9 through 11 to add captions for the table cells in the rest of the first row as shown in the
following table.

C O L UM N C A P T IO N EXP RESSIO N

3 CustomerNo_CustLedgerEntryCaption

4 PostingDate_CustLedgerEntryCaption

5 DocumentType_CustLedgerEntryCaption

6 DocumentNo_CustLedgerEntryCaption

7 Description_CustLedgerEntryCaption

8 Skip this cell. You'll use this cell later.

9 CurrencyCode_CustLedgerEntryCaption

10 Amount_CustLedgerEntryCaption

11 OriginalAmtLCY_CustLedgerEntryCaption

12 RemainingAmtLCY_CustLedgerEntryCaption

13. Right-click the left-most grouping cell (the cell that contains the Entr yNo_CustLedgerEntr y field) in the
table, select Text Box Proper ties , in the Text Box Properties window, select the Visibility tab, under the
Change display options , select the Hide option.
14. Select the first row in the table, in the Proper ties pane, under Fill , set the BackgroundColor property
to Dim Grey .
15. Right-click the cell in the row2, column 2, and then choose Expression to open the Expression window.
16. In the Categor y column, select Fields (DataSet_Result) , in the Values column, double-click
Entr yNo_CustLedgerEntr y , and then choose the OK button. The Set expression for : Value box
contains the following value: =Fields!EntryNo_CustLedgerEntry.Value
17. Repeat steps 15 and 16 for row 3 to add fields from the ledger entry dataset. Put the fields under the
corresponding captions.
18. Select the row that you filled in and set the BackgroundColor property to Silver .
19. Build the project, inspect the Output pane, and make sure that there are no build errors.
20. Select the second table row, right-click the shaded border to the left, choose Inser t Row , and then
choose Below . The table should now have three group rows, one group data row, and one table footer
row. This row will store the captions of Detailed Cust. Ledg. Entr y data item.
21. Add the captions and fields for the Detailed Cust. Ledger Entr y table as shown in the following table.

T H IRD RO W ( C A P T IO N ) F O RT H RO W ( F IEL DS)

EntryNo_DetailedCustLedgEntryCaption EntryNo_DetailedCustLedgEntry.Value

EntryType_DetailedCustLedgEntryCaption EntryType_DetailedCustLedgEntry.Value

PostingDate_DetailedCustLedgEntryCaption. PostingDate_DetailedCustLedgEntr.Value

DocumentType_DetailedCustLedgEntryCaption DocumentType_DetailedCustLedgEntry.Value

DocumentNo_DetailedCustLedgEntryCaption DocumentNo_DetailedCustLedgEnt.Value

TransactionNo_DetailedCustLedgEntryCaption TransactionNo_DetailedCustLedgEntry.Value

JournalBatchName_DetailedCustLedgEntryCaption JournalBatchName_DetailedCustLedgEntry.Value

AmountLCY_DetailedCustLedgEntryCaption AmountLCY_DetailedCustLedgEntr.Value

DebitAmountLCY_DetailedCustLedgEntryCaption DebitAmountLCY_DetailedCustLedgEntry.Value

CreditAmountLCY_DetailedCustLedgEntryCaption CreditAmountLCY_DetailedCustLedgEntry.Value

22. Shrink the column that contains the Customer No. field of the Cust. Ledger Entry to about half of its
size.
23. Right-click the column header that contains the Customer No. field, choose Inser t Column , and then
choose Right .
24. Select the cell that contains the Customer No. caption and the empty cell that you created, and then
choose Merge Cells to merge the two cells.
25. Repeat step 24 to merge the cell that contains the value of the Customer No. field and the empty cell
that you created.
26. Assign the expression from the Entr yType caption and field cells of the Detailed Cust. Ledg. Entry to the
empty cell that you created to the right. You may have to cut the expressions and paste them into the
empty cells.
27. Repeat 26 to move the Entr yNo caption and field 1 cell to the right. This makes sure that the EntryNo
and the EntryType data are located directly under the CustomerNo cell.
The following illustration shows EntryNo and the EntryType cells directly under the CustomerNo cell

28. Repeat steps through 27 to put the Transaction No. and Journal Batch Name captions and fields
under the Description data. This creates a blank cell under the CurrencyCode field.
29. Select the third row and set the BackgroundColor property to Yellow and then set the
BackgroundColor property of the fourth row to Khaki .
Viktor will now hide all empty cells and add the totals to the footer row. To hide empty cells Viktor will
add a filter that selects rows that have [EntryNo] value that is greater than zero.
To hide empty cells and add totals
1. Select the first row, right-click the shaded border to the left of the row, choose Row Group , and then
choose Group Proper ties .
2. In the Group Proper ties window, select the Filters tab, and then choose the Add button.
3. Set Expression to [Entr yNo_CustLedgerEntr y] , change Text to Integer , set Operator to > , set Value
to 0 , and then choose the OK button.
The filter that is set applies to the other rows in the table.
4. In the Group Proper ties window, under the Filters tab, verify that the Expression box contains
[EntryNo_CustLedgerEntry].
Viktor will now add the total of the amount field to the footer row of the table, format the cells and hide
the total cell if customer ledger entry isn't available.
5. In the last row of the table, right-click the empty cell under the Amount (LCY) field, and then choose
Expression .
6. In the Categor y column, select Fields (DataSet_Result) , in the Values column double-click
Amount_CustLedgerEntr y , and then change the expression in the Set expression for : Value box to
the following value: =Sum(Fields!Amount_CustLedgerEntry.Value) . Choose the OK button.
7. In the Proper ties window, locate the Format property, choose the drop-down arrow and select
Expression .
8. In the Expression window, enter the following formatting expression in Set expression for : Value box:
=Fields!Amount_CustLedgerEntryFormat.Value . Choose the OK button.

NOTE
Alternatively, you set this value by double-clicking Amount_CustLedgerEntr yFormat in the Values field of
Fields(DataSet) category.

9. Select the two empty cells to the left of the total cell, right-click the cells, and then choose Merge Cells .
10. Right-click the merged cell, choose Expression , choose the Parameters category, and then set the
caption to Total_Caption
11. Set the BackgroundColor property of the cells that contain the total and total caption to Red .
If you run the report now, the total amount cell will be displayed even if there are no ledger entries. Viktor
will add an expression to hide the footer row when there are no ledger entries.
12. Select the last row, in the Proper ties window, locate the Hidden property, choose the drop-down arrow,
and then choose Expression .
13. In the Expression window, in the Set expression for : Hidden box, enter the following expression to
hide the row: =Fields!EntryNo_CustLedgerEntry.Value = 0 . Choose the OK button. This hides the row if
there are no entry values.
14. Right-click the left-most cell in the last table row, select Text Box Proper ties , select the Visibility tab,
under Change display options , select the Hide option, and then choose the OK button.
The next step is to add the data from the Sales Header table.
To add the sales header data
1. From the Toolbox , drag a Table control to the List control, and then put the table control under the table
that contains the Cust. Ledger Entr y table
2. Right-click a column and add columns to create five columns for the table.
3. Delete the first header row from the table.
4. Right-click the data row, choose Tablix Proper ties , verify that the DataSet name is set to
DataSet_Result , and then choose the OK button.
5. Right-click the data row, choose Add Group , and then choose Parent Group to open the Tablix group
window.
6. Select the Group by: option and then choose the fx button to open the Expression window.
7. In the Categor y column, select Parameters , and then in the Values , column double-click
Sales_Document_Caption . Verify that the Set expression for : Value box contains the following
value: =Parameters!Sales_Document_Caption.Value . Choose the OK button.
8. In the Tablix group window, select Add group header , and then choose the OK button.
9. Right-click the first row in the table, choose Inser t Row , and then choose Inside Group – Above .
10. Reduce the size of the first column, and then in the Proper ties window, under Visibility , set the Hidden
property to True . This hides the first column.
11. In the first table row, merge all the cells except the first grouping cell.
12. Right-click the merged cell, and then choose Expression .
13. In the Categor y column, select Parameters , and then in the Values column double-click
Sales_Document_Caption . Verify that the Set expression for : Value box contains the following
value: =Parameters!Sales_Document_Caption.Value . Choose the OK button.
14. Modify the expression to =First(Parameters!Sales_Document_Caption.Value) .
15. Right-click the cell in row2, column 2, and then choose Expression to open the Expression window.
16. In the Categor y column, select Parameters , and then in the Values column double-click
DocumentType_SalesHeader . Verify that the Set expression for : Value box contains the following
value: Parameters!DocumentType_SalesHeaderCaption.Value .
17. Modify the expression to the following value: =First(Parameters!DocumentType_SalesHeaderCaption.Value)
and then choose the OK button.
18. Right-click the cell that is under the caption that you created, choose Expression . In the Categor y
column, select Fields (DataSet_Result) , and then in the Values column double-click
DocumentType_SalesHeader . Choose the OK button. Verify that the Set expression for : Value box
contains the following value: =Fields!DocumentType_SalesHeader.Value
19. Repeat steps 15 through 18 and add the following captions and the corresponding fields.

C A P T IO N C O RRESP O N DIN G F IEL D

No_SalesHeaderCaption No_SalesHeader

PostingDate_SalesHeaderCaption PostingDate_SalesHeader

PricesIncludingVAT_SalesHeaderCaption PricesIncludingVAT_SalesHeader

Amount_SalesHeaderCaption Amount_SalesHeader

20. Select the first two rows and in the Proper ties window, set the BackgroundColor property to Lime .
21. Select the data row (last row), in the Proper ties window, set the BackgroundColor property to
Turquoise .
Viktor will now set a filter that hides empty rows.
To set a filter hide empty row
1. Select any row from this table, right-click the shaded border to the left of the table, and then choose
Tablix Proper ties .
2. Choose the Filters tab and then choose the Add button.
3. In the Expression list box, select No_SalesHeader , set Operator to > , set Value to 0 , and then choose
the OK button.
4. Save the report.

Building and Running the Report


Viktor will run the report to view how it looks like. For this, do the following steps:
1. Make sure that the "startupObjectId" is set to the Id of the report object and the "startupObjectType" to
Report in the launch.json file.

2. Press the F5 key to compile and run the report in Dynamics 365 Business Central.
3. If you haven't switched off the UseRequestPage Property you'll be shown a request page in the Web
Client.
The following illustration shows an example of the request page that is displayed when the report is run.

If you choose the Preview button on the request page, the report will be displayed with the RLD layout
created.
Viktor can now add advanced features to the report. He can add features such as displaying the company name
and logo on every page on the report. He might also want to add features that enable users to apply filters on
the request page.
See Also
Report Overview
Defining a Report Dataset
Creating an RDL Layout Report
Adding Barcodes to Reports
2/6/2023 • 7 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

This article explains how to add barcodes to reports using the barcode functionality in Business Central.

Overview
The barcode functionality lets you convert an alphanumeric value in a report dataset into a barcode on a
generated report. The functionality is provided by the Barcode module of the System Application. The module
includes the objects and tools that you need to add barcodes to reports. This section provides a brief overview
of the Barcode module. For more information about the module, see the AL Extensions on GitHub.
Barcode providers and encoders API
There are two key components involved in barcodes: the barcode provider and the barcode encoder. A barcode
provider includes a library of different barcode fonts and symbologies available for use in reports. Barcode
encoders are the components of the provider that encode the data strings of a report dataset to a specific font
specification and symbology.
The Barcode module provides an API that lets you create custom barcode providers and encoders for one-
dimensional and two-dimensional fonts. The API consists of several public objects, including:
Interfaces for the barcode providers and encoders
Enums for the barcode symbologies
A table object for storing encode settings. For example, you can enable an extended character set or
checksums in Code39, or change the code set used in Code128.
Built-in providers and font support
The Barcode module also includes the following predefined providers and encoders that implement the
interfaces. These providers support several fonts from IDAutomation.
Codeunit 9215 IDAutomation 1D Provider is the barcode provider for IDAutomation one-dimensional
fonts
Codeunit 9221 IDAutomation 2D Provider is the barcode provider for IDAutomation two-dimensional
fonts
With Business Central online, the IDAutomation fonts are automatically available as part of the service. So you
can start adding barcodes to reports right away. For a description of the available fonts, see Barcode Fonts with
Business Central Online.
For Business Central on-premises, you'll have to purchase and install the barcode fonts. If you choose the
IDAutomation fonts, you can use the same built-in providers and encoders as Business Central online - without
making any changes. Or, you can purchase fonts from other providers, then use the API to create custom
barcode providers and encoders.

Getting started
The tasks involved in creating a report that displays a barcode are as follows:
1. (optional) Install the fonts on your development computer or virtual machine.
You don't need the barcode fonts installed on the computer you're using when developing a report and
its layouts. Without the font, the report won't show the barcode. But if you then test the report, for
example in an online sandbox, it will be shown on the report.
2. If you don't want to use the built-in IDAutomation providers and encoders, create your own provider and
encoders using the API.
When creating your own, adhere to the interface in the Barcode module. Use the built-in providers and
encoders as a starting point. Consider contributing to the open-source project if you do.
3. In AL code, add the barcode to a report or report extension object.
a. Determine the source of the data string that you want to display as a barcode in the report, for
example, like a field in the underlying table.
b. Add a column to the report dataset to hold the encoded string for the barcode.
c. Encode the data string as the barcode.
To represent a string as a barcode in a report, you encode it according to the symbology you want.
For this step, you add code to:
Declare the provider by using the barcode provider interface
Declare the barcode font by using the barcode symbology enum
Call the font encoder on the data string
For an example of how it's done, see Adding the barcode to the report dataset.
4. In the report layout, add the barcode field and apply the barcode font to the field.
For more information, see Adding the barcode to the report layout.

Adding the barcode to the report dataset in AL


The following code shows an example report that displays the No. field of the Item table as a barcode. The first
example uses the Code 39 one-dimensional font from the built-in IDautomation barcode provider. The example
generates both a Word and RDL layout. The second example shows how you to do the same for a QR-Code two-
dimensional barcode.
One-dimensional
Two-dimensional
report 50100 ItemBarcodeReport1D
{
UsageCategory = Administration;
ApplicationArea = All;
DefaultLayout = Word;
Caption = 'Item Barcodes';
WordLayout = 'ItemBarcodes.docx';
RDLCLayout = 'ItemBarcodes.rdl';

dataset
{
dataitem(Items; Item)
{
DataItemTableView = SORTING("No.");
RequestFilterFields = "No.";
RequestFilterHeading = 'Items';

// Column that provides the data string for the barcode


column(No_; "No.")
{
}

column(Description; Description)
{
}

column(Unit_Price; "Unit Price")


{
}

// Column that stores the barcode encoded string


column(Barcode; EncodedText)
{
}

trigger OnAfterGetRecord()
var
BarcodeString: Text;
BarcodeSymbology: Enum "Barcode Symbology";
BarcodeFontProvider: Interface "Barcode Font Provider";

begin
// Declare the barcode provider using the barcode provider interface and enum
BarcodeFontProvider := Enum::"Barcode Font Provider"::IDAutomation1D;

// Declare the font using the barcode symbology enum


BarcodeSymbology := Enum::"Barcode Symbology"::"Code39";

// Set data string source


BarcodeString := "No.";

// Validate the input. This method is not available for 2D provider


BarcodeFontProvider.ValidateInput(BarcodeString, BarcodeSymbology);

// Encode the data string to the barcode font


EncodedText := BarcodeFontProvider.EncodeFont(BarcodeString, BarcodeSymbology);
end;
}
}

var
// Variable for the barcode encoded string
EncodedText: Text;
}
Adding the barcode to the report layout
When done modifying the report or report extension objects, build the project to create the layout documents.
Then create the report layouts as usual (see Creating an Word Layout Report or Creating an RDL Layout Report).
To display the barcode the layout, you'll have to do two things:
1. Add the barcode encoded string column from the dataset to the layout.
Referring to the example above, you'd add the Barcode column.
2. Apply the barcode font to the barcode column by using the text features of Word or Report Builder.
For Word layouts:
In Word, select barcode column control, press Ctrl+D, then enter or select the barcode font name.

For RDLC layouts


You can use Microsoft Report Builder or modify the XML of .rdl file directly from Visual Studio
Code. In Microsoft Report Builder, right-click the barcode column control, select Text Box
Proper ties > Font .

The following code snippet illustrates how to make the same modifications directly in the .rdl file
from Visual Studio Code:
...
<TablixCell>
<CellContents>
<Textbox Name="Barcode">
<Paragraphs>
<Paragraph>
<TextRuns>
<TextRun>
<Value>=Fields!Barcode.Value</Value>
<Style>
<FontFamily>IDAutomationHC39M</FontFamily>
...

When using IDAutomation fonts, specifying the font is different for one-dimensional and two-
dimensional fonts:
One-dimensional barcode fonts can have several versions, where each version has a different name.
For example, Code 39 includes IDAutomationHC39S , IDAutomationHC39M , and many more. In
this case, set the font to match the specific font version you want.
Two-dimensional barcodes, other than Maxicode, use the same font name. To specify a two-
dimensional font, use IDAutomation2D .
For Maxicode two-dimensional barcode, use IDAutomation2D MaxiCode .

IMPORTANT
When modifying a report layout for production environment, it's important that the font you specify is installed
on the Business Central service. Otherwise, the barcode won't display correctly on the report. So for Business
Central online, be sure to specify a purchased font name (like IDAutomationHC39M ); not an evaluation font
name (like IDAutomationSHC39M Demo ). For more information, see Font versions and names.

Setting up Business Central on-premises deployment


With Business Central on-premises, you'll have to install the barcode fonts on the computer that runs the
Business Central Server. As a minimum, you must install the fonts for the user that runs the Business Central
Server instance, that is, the service account. It's easiest just to install the font for all users.
To install the fonts, follow the instructions from the font supplier or see Add a Font. After you install the fonts,
restart your computer.

See Also
Request Pages
Creating an RDL Layout Report
Creating a Word Layout Report
Developing Extensions
AL Development Environment
Formatting Decimal Values in Fields
2/6/2023 • 5 minutes to read • Edit Online

This article describes how you can format the decimal values that appear in fields on table, pages and reports.
For example, you can change how the data appears in a Cue on the Role Center page. To format data, you use a
combination of the AutoFormatType Property, AutoFormatExpression Property, and DecimalPlaces Property of
the field. These properties work together to enable you to specify the following:
Display amounts and unit amounts in another currency.
Specify the number of decimal places.
Specify whether to display a thousand separator.
Specify characters before and after the value, such as currency signs or %.

Implementation overview
When a field is used on a page or report, you can set the AutoFormatType and AutoFormatExpr properties
directly on the page field or report field (column), or you can set them on the underlying table field. If you
specify the properties on the table field, then the format applies wherever the field is used. Specifying the
properties on the page or report field will only apply the format to the specific page or report. If you specify the
properties on the table field and the page or report field, then the settings on the page or report field take
precedence.
When you use the AutoFormatType and AutoFormatExpression properties to format a field, two events are
raised by the system codeunit 45 Auto Format : OnResolveAutoFormat and OnAfterResolveAutoFormat.

Setting up data formatting


The settings for the AutoFormatType , AutoFormatExpression , and DecimalPlaces properties will depend
on the type of data that is displayed, for example, this could be currency amounts, unit amounts, simple
decimals, or ratios. For the most part, the AutoFormatType property is the primary setting, which in turn
determines the options for setting the DecimalPlaces and AutoFormatExpr properties.
If the AutoFormatType is not set or is set to an incorrect property value, then the default setting is used,
regardless of whether the AutoFormatExpression or DecimalValues properties are set. The default setting
uses AutoFormatType = 1 and AutoFormatExpression = '' .
The following tables describes how to set each of the properties to achieve the format that you want.

Setting the DecimalPlaces property


With the following set up, the AutoFormatExpression property is ignored.

A UTO F O RM AT T Y P E P RO P ERT Y DEC IM A L P L A C ES P RO P ERT Y USA GE DESC RIP T IO N


A UTO F O RM AT T Y P E P RO P ERT Y DEC IM A L P L A C ES P RO P ERT Y USA GE DESC RIP T IO N

0 Set to the number of decimal places Use this configuration when you want
that you want to display for the value. to format the decimal value according
the Standard Format 0 (which is the
default format) with a specific number
of decimal places.

For example, if the value is a US


decimal -76543.21 and you set the
DecimalPlaces property to 0 , then
the value appears as 76,543 . The
properties will look like this:

AutoFormatType = 0;
DecimalPlaces = 0;

Setting the AutoFormatExpression property


With the following setup, the DecimalPlaces property is ignored.

A UTO F O RM AT T Y P E P RO P ERT Y A UTO F O RM AT EXP RESSIO N P RO P ERT Y USA GE DESC RIP T IO N

1 Set to return a currency code, such as Use this configuration when you want
USD or IDR. The blank currency code to format the data as an amount. For
'' denotes LCY and is the default example, a sales order will use two
value. decimals when the currency is defined
as US dollar and no decimals when the
currency is defined as IDR (Indonesian
rupiah). For example:

AutoFormatType = 1;
AutoFormatExpression = 'IDR';

2 Set to return a currency code such as This is similar to the previous


USD or IDR. The blank currency code configuration where the
'' denotes LCY and is the default AutoFormatType property is set to
value. 1 , except you use this configuration
when you want to format the data as a
unit amount.
A UTO F O RM AT T Y P E P RO P ERT Y A UTO F O RM AT EXP RESSIO N P RO P ERT Y USA GE DESC RIP T IO N

10 Set to the property according to the Use SubType 1 to add the currency
following syntax: symbol and use the amount type
precision. You use SubType 2 for unit
'[SubType][,<currencycode or amount precision. For example, set the
expression>[,<PrefixedText>]]'
property to '1,USD' to add the $
symbol, like $543.21 .
SubType can be 1 , 2 , another
number, or omitted: AutoFormatType = 10;
AutoFormatExpression = '1,USD';
1 sets the value to an amount type
(see 1 above). 2 sets the value to a If you omit the SubType, you can use
unit amount type (see 2 above). The this configuration to customize the
syntax for these two settings is: format based on one of the standard
formats. This option enables you to
'SubType,<currencycode[,
<PrefixedText>]'
specify characters before and after the
decimal value, such as currency signs $
and percent %.
If you omit the subtype or use a
number other than 1 or 2, the syntax
For example, if you want to prefix the
is:
decimal value with a $ , include a
thousand separator, and have a
'<CustomNumber>, <expression>[,
<PrefixedText>]' maximum of two decimal places, such
as $76,453.21 , then you can set the
where <expression> sets the properties to:
precision and one of the standard
AutoFormatType = 10;
formats. For more information, see
Standard Formats. AutoFormatExpression =
'$<precision, 2:2><standard
format, 0>'

If you want to display the decimal


value as a percentage, then you can
add % at the end of the setting. For
example:

AutoFormatType = 10;
AutoFormatExpression =
'<precision, 1:1><standard
format,0>%'

When you include a % at the end of


the setting, then the decimal value is
assumed to be the ratio, and the
decimal value will be multiplied by 100.
For example, a value of 0.98 will be
formatted to 98%.

11 Set the property to the standard Use this option when you want full
format as explained below. For control over the formatting. The
example: format string will be applied exactly as
specified in the AutoFormatExpr
'<Precision,3:3><Standard property.
Format,0>'

Precision
The precision determines the minimum and maximum number of decimal points for values. The precision takes
the format <precision,minimum:maximum> . For example, <precision,minimum:maximum> sets the data with a
minimum of 2 and a maximum of 3 decimal places.
Standard formats
The following table describes the standard formats that are available for the AutoFormatExpr property when
the AutoFormatType property is set to 10.

STA N DA RD F O RM AT F O RM AT DESC RIP T IO N EURO P E DEC IM A L EXA M P L E US DEC IM A L EXA M P L E

0 <Sign><Integer -76.543,21 -76,543.21


Thousand><Point or
Comma><Decimals>

1 <Sign><Integer><Point or -76543,21 -76543.21


Comma><Decimals>

2 <Sign><Integer><Point or -76543.21 -76543.21


Comma><Decimals>

3 <Integer Thousand><Point 76.543,21- 76,543.21-


or Comma><Decimals>
<Sign>

4 <Integer><Decimals> 76543,21- 76543.21-


<Point or Comma><Sign>

9 XML format -76543.21 -76543.21

See Also
AutoFormatType Property
AutoFormatExpression Property
DecimalPlaces Property
Entitlements and Permission Sets Overview
2/6/2023 • 5 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

Business Central uses two main concepts for defining access to functionality: Entitlements and permissions.
Entitlements describe which objects in Business Central a customer is entitled to use according to the
license that they purchased from Microsoft or according to the Azure Active Directory role that they have
assigned in Microsoft 365 Admin Center, such as Global Administrator. Entitlements are only used in the
online version of Business Central.
Permissions describe which objects an administrator or a partner has given the user.
Permission sets combine objects permissions in logical groups (or sets), which can then be assigned to
the users explicitly or through a user group.
For more information about assigning licenses, see Licensing in Dynamics 365 Business Central. For more
information about how to create and assign permissions, see Assign Permissions to Users and Groups.

Permission Set scope


A Business Central solution contains a number of predefined permission sets that are added by Microsoft or by
your software provider (by an ISV application that you installed from AppSource).
Permission sets included with Microsoft and AppSource apps defined as AL objects are of the type System .
End-users cannot create or edit these types of permission sets or the permissions within them. However, they
can copy these permission sets to define their own permission sets and permissions. Permission sets that users
create, from new or as copies, are of the type User-Defined and they can be edited.

Creating entitlements and permission sets in AL


When developing an app, entitlements and permission sets are handled as objects in AL, and existing
permission sets can be extended in AL. The following object types are used for handling entitlements and
permissions:
Entitlement Object
PermissionSet
PermissionSetExtension

NOTE
In the current version of Dynamics 365 Business Central entitlements can only be included with Microsoft apps (enforced
by the AppSource cop rules and the technical validation checks that we run for the apps submitted to AppSource). These
objects will become available for the ISV apps when we introduce ability to monetize AppSource apps in one of our future
releases.

Upgrade considerations
Starting with Business Central 2021 release wave 1 (v18.0), the Business Central demo database, which is
shipped with our on-premises installation, doesn't contain any data in the Permission Set and Permission
tables in the application database. Instead, the System permission sets and permissions are provided as AL
objects of type PermissionSet and PermissionSetExtension , included with Microsoft apps.
The application database tables that used to store the entitlements won't contain any data either, because
entitlements are now defined as AL objects.
Business Central server configuration file (CustomSettings.config) includes a setting that allows on-premises
administrators to decide whether they want to continue using the permissions defined as data or as AL objects:

<add key="UsePermissionSetsFromExtensions" value="true" />

The default value for this setting is true , meaning that the server will be retrieving all System permission sets
and permissions from the AL objects of type PermissionSet and PermissionSetExtension . With the value for this
setting set to true , the permissions data, in case it is still present in the application database, will be
disregarded.
It's not possible to customize the System permission sets and permissions used in the online version of
Business Central. End-users can only copy these types to new permission sets, which they can then adjust to
their needs. For more information, see Assign Permissions to Users and Group.
In the on-premises version of Business Central, even though it's not recommended, the partners can customize
the permission sets and permissions shipped in the application database. In this case, as for any upgrade before,
the changes in Microsoft permissions should be merged with the customized permissions by partners during
upgrade.
Although starting with Business Central 2021 release wave 1 (v.18.0), System permissions are no longer
shipped as data in the application database, the partners can use the same procedure as before to export the
new permissions that are defined using AL objects. The new permission sets and permissions can be exported
into XML file by running XMLport 9171 Import/Export Permission Sets, making it possible to compare and
merge the customized permission sets in your old database with the newly shipped permission sets. Find more
details, see Export and Import Permission Sets and Permissions.
How to upgrade permission sets
When upgrading to version 18, first decide whether you want to use the permissions defined as data or switch
to permissions defined as AL objects. Then, follow the guidelines at Upgrading Permission Sets for details on
how to do the upgrade.

Earlier versions of Business Central


In releases of Business Central prior to 2021 release wave 1 (v18.0), System and Extension permissions and
entitlements were defined as data in the application database:
Entitlements tables:
Entitlement
Entitlement Set
Membership Entitlement
Permissions tables:
Permission Set
Permission
Keeping such sensitive information as data comes with additional maintenance, security, and audit risks for the
software providers (ISVs). Changes applied to this data should ideally be well traceable, easy to update and
maintain. Starting with Business Central 2021 release wave 1, the System permissions and entitlements are
defined in code, using Entitlement, PermissionSet, and PermissionSetExtension AL objects. This change provides
ISVs with all of the advantages of using the AL Language extension in Visual Studio Code and source control
systems (as Visual Studio Online and GitHub) to design, get an overview, and track changes to the objects that
describe user access.
Turning this data into code has another significant advantage: the ability to apply hotfixes to the entitlements
and permissions in the same way that the hotfixes are applied to the apps themselves, simply by updating an
app to a new version which carries fixed code. This improves Business Central support agility considerably,
ultimately improving customer satisfaction with the service.
And finally, the new AL objects are envisioned to become the core building blocks in the story of monetizing the
AppSource apps. It's through these new AL objects that AppSource ISVs will be able to define which capabilities
of their apps should be made available to their users, when the customers purchase their app licenses. With
Business Central 2021 release wave 1, we're paving the way by moving the entitlements and permission sets
into AL objects for Microsoft apps, so that ISVs can follow the same approach for their apps, when the
monetization story is introduced with one of the next releases of Business Central.
User-Defined permission sets and permissions, and functionality around them, remain unchanged. They're still
stored as data in the tenant database:
Tenant Permission
Tenant Permission Set
Permission sets and permissions included with apps in XML format will continue to work as before, however, we
recommend you to start using the AL objects of type PermissionSet and PermissionSetExtension instead.

See Also
Get Started with AL
Entitlement Object
PermissionSet Object
PermissionSet Extension Object
Permission Set Object
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

The permission set object in Business Central describes permissions on objects. Permission sets are building
blocks used to compose assignable permission sets and entitlements. Assignable permission sets are
permissions that an admin can assign to users in Business Central, using the Permission Sets page. An
entitlement is a collection of permission sets that constitute a set of meaningful permissions for a user.
Some permission sets can be non-assignable, meaning that they aren't discoverable and assignable in the UI in
Business Central, instead they can be used as building blocks to compose functional assignable permission sets.
For information about which permissions can be assigned to objects, see Permissions on Database Objects.

Designing with cautiousness


If a permission set is extended through AL, the extension will make additive changes to the permission set. This
behavior means an extension can provide elevated privileges to an otherwise limited set of permissions.
Building permission sets that can be extended must be done carefully with this behavior in mind.

Snippet support
Typing the shortcut tpermissionset will create the basic layout for a permission set object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Generate permission set for an object


APPLIES TO: Business Central 2022 release wave 2 and later

When adding new AL objects, it's easy to forget to update the permissions. With the
al.generatePermissionSetForExtensionObjects command, you can generate or update a permission file for the
active project in Visual Studio Code. Choose to create a new permission file or select an existing file to make
updates to. For more information, see AL Language Extension Configuration.

Permission set example


The following example illustrates a permission set Sales Person with permissions given to data in tables, each
with different level of access. The Assignable property is set to true , which allows the permission set to be
assigned to a user. The Permissions property is set to the list of objects to give permissions to. The RIMD access
assigned to data in the Customer table provides full access, whereas, for example, access is limited for data in
the Currency table only allowing full read and modify permission.
NOTE
The name of the permissionset object is limited to 20 characters when the Assignable property is set to true .
Otherwise, it's limited to 30 characters. Exceeding the limit will throw the diagnostic Compiler Error AL0305.

permissionset 50134 "Sales Person"


{
Assignable = true;
Caption = 'Sales Person';

Permissions =
tabledata Customer = RIMD,
tabledata "Payment Terms" = RMD,
tabledata Currency = RM,
tabledata "Sales Header" = RIM,
tabledata "Sales Line" = RIMD;
}

The following example of a permission set illustrates assigned permissions to run codeunits. With the
IncludedPermissionSets property, we specify that the permission set Sales Person is also included in
MyPermissionSet .

permissionset50135MyPermissionSet
{
Assignable = true;
Caption = 'My PermissionSet';
IncludedPermissionSets= "Sales Person";

Permissions=
tabledataVendor=RIm,
codeunit SomeCode =x,
codeunit AccSchedManagement=X;
}

You can also use the ExludedPermissionSets property to exclude permissions defined in other permission sets.
To learn more, see Composing Permission Sets From Other Permission Sets.

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Extension Object
Permissions on Database Objects
Assignable Property
IncludedPermissionSets
Permissions Property
Permission Set Extension Object
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

The permission set extension object in Business Central adds permissions to an existing permission set defined
in AL. A permission set extension object cannot remove permissions from an existing permission set, it can only
add permissions. If you, for example, add an extension to Business Central, you can use permission set extension
objects to grant permissions to the objects in your extension. This means that the admin of Business Central
does not have to assign additional permission sets to the users, because that automatically happens when the
extension is installed, and the permissions go away if the extension is uninstalled.
For information about which permissions can be assigned to objects, see Permissions on Database Objects.

Designing with cautiousness


If a permission set is extended through AL, that extension will make additive changes to the permission set. This
means that an extension can provide elevated privileges to an otherwise limited set of permissions. Building
permission sets that can be extended must be done carefully with this in mind.

Snippet support
Typing the shortcut tpermissionsetextension will create the basic layout for a permission set extension object
when using the AL Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Permission set example


The following permission set extension example extends the Sales Person permission set by adding direct
insert and delete permissions to the Currency table data.

permissionsetextension 50140 "Extended Sales Doc" extends "Sales Person"


{
Permissions = tabledata Currency = ID;
}

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Object
Permissions on Database Objects
Assignable Property
Permissions Property
Permissions on Database Objects
2/6/2023 • 2 minutes to read • Edit Online

This section provides an overview of permissions on objects in Dynamics 365 Business Central.

Permissions
If you have been granted permission to read a page, then you can open the page and view the data that it
displays. If, however, you do not have write permission, you are not allowed to enter data into this page.
Sometimes, when you open a page it displays information from several tables. To access this page, you must
have permission to view all the data displayed by the page. You might not have permission to read directly from
all the tables that the page uses. In this case, you must have indirect permission to read from the tables in
question. Having indirect permission to a table means that you cannot open the table and read from it but can
only view the data it contains indirectly through another object, such as a page or report, that you have direct
permission to access.
Dynamics 365 Business Central has a number of standard predefined security permission sets. You can use
these permission sets as defined or you can change a permission sets to suit your particular needs. You can also
create your own permission sets and assign them the permissions that you want.
Permissions on Objects
The following table describes the permissions that can be assigned for specific objects. When assigning
permissions by using the object types PermissionSet Object and PermissionSet Extension Object these
permissions have been shortened. The table illustrates the abbreviations used.
Permissions on tabledata are specified with the following abbreviations:

P ERM ISSIO N DESC RIP T IO N A B B REVIAT IO N IN A L

Read You can read data. R for direct read access, r for
indirect read access.

Insert You can insert data. I for direct insert permission, i for
indirect insert permission.

Modify You can modify data. M for direct modify permission, m


for indirect modify permission.

Delete You can delete data. D for direct delete permission, d for
indirect delete permission.

Permissions on all objects are specified with the following abbreviations:

P ERM ISSIO N DESC RIP T IO N A B B REVIAT IO N IN A L

Execute You can run this object. X for direct execute permissions, x
for indirect execute permissions.

Wildcard
The wildcard can be used as a shortcut to assign multiple permissions at a time, such as:
Permissions = codeunit * = X;

IMPORTANT
The wildcard must be used with caution, because when it is used in a permission set it grants the permission to all objects
of that type across all permissions. If a permission set with a wildcard is included in an entitlement, it only covers the
objects of that type in the current extension.

Example
All of the permissions illustrated above can be combined into a group of permissions for any given object. For
example:

...
Permissions =
tabledata Customer = RIMD, // Full access
tabledata "Payment Terms" = RMD, // Full read, modify, and delete access - no insert
tabledata Currency = rimd, // Full indirect access
tabledata "Sales Header" = RIM, // full read, insert, and modify access - no delete
tabledata "Sales Line" = RIMD, // Full access
report "Sales Statistics" = X; // Full access
...

See Also
Get Started with AL
Entitlements and Permission Set Overview
Permission Set Object
Permissions on Database Objects
Inherent Permissions
2/6/2023 • 2 minutes to read • Edit Online

With inherent permissions, developers can now grant permissions to a method or event while code executes. As
soon as the code execution is completed, permissions are revoked. Inherent permissions simplify the overall
management and maintenance work of permission sets. With it, a specific AL method or event can get the
elevated permissions necessary to finish the task at hand without getting permission errors. And it helps tighten
overall security by limiting long-term user permissions and giving permissions to the code process instead.
Let’s say a salesperson wants to make a report that includes certain critical pieces of information. In the
background, a method will run a query to fetch the information from the table holding classified data. With
inherent permissions, instead of managing permissions for that salesperson, a developer can add the
permission permanently into the specific code path. This method will be granted permissions for the given
object, which in this case is a table. Now, whenever an authorized person runs this method, the needed
permissions are in place to complete the request.

NOTE
For now, the InherentPermissions attribute is available for Business Central on-premises only. It'll be added to Business
Central online in a later version.

TIP
It's better to use the inherent permissions for small dedicated procedures or system tasks that don't risk data exposure to
users.

Syntax
[InherentPermissions(PermissionObjectType: PermissionObjectType, ObjectId: Integer, Permissions: Text [,
InherentPermissionsScope: InherentPermissionsScope])]

To learn more about the syntax of the InherentPermissions attribute, see InherentPermissions Attribute.

Example
Let's look at a code example for the InherentPermissions attribute.

[InherentPermissions(PermissionObjectType::TableData, Database::Customer, 'r',


InherentPermissionsScope::Both)]

Procedure GetCustomersLocation(): CustomerLocation

Referring to the example explained above, let's say the report needs to show which location has more sales for
the quarter. As it's not ideal to grant access to all data belonging to customers, read permission is granted to the
method instead. It will only fetch the customer's location and leave other details (such as name, address, and so
on) private.
Inherent Entitlements
The inherent permissions and inherent entitlements together, grant more flexibility to the developers that they
can assign permissions to their methods, events, and objects. Developers can define inherent entitlements for
their objects like codeunit, table, page, and so on. In this way, the developers equip all users to have enough
access that they can carry out essential tasks without any halt. And regardless of what access their present
license or entitlement grant them. To learn more about inherent entitlements, see InherentEntitlements Property.

NOTE
Specifying InherentPermissionsScope is optional and the default is Both that includes permissions and entitlements. To
read about different types of scope, see InherentPermissionsScope Option.

See also
Entitlements and Permission Sets Overview
Permission Set Object
Exporting Permission Sets to XML
2/6/2023 • 2 minutes to read • Edit Online

Permission sets that exist in Dynamics 365 Business Central can be exported and packaged for your extension
directly from the client, instead of defining XML by hand. These permission sets are also known as tenant
permissions, and are shown in the UI as Extension permissions. The underlying functionality of permissions
has changed with the latest version of Dynamics 365 Business Central.

IMPORTANT
With the latest version of Dynamics 365 Business Central permissions are no longer defined as data in the application
database. Permissions that can be created by using AL objects are called system permissions. For more information, see
Entitlements and Permission Sets Overview.

To export permission sets from Dynamics 365 Business Central


1. In Dynamics 365 Business Central, search for Permission Sets , and then choose the relevant link.
2. On the Permission Sets page, choose the permissions that you want to export, and then choose Expor t
Selected Permissions .
3. In the Expor t Permission Sets dialog, choose to export permission sets only for the application, only for
the tenant, or for both.
4. Save the file to your extension folder.
5. Delete the permission sets from Dynamics 365 Business Central.
You can generate a permission set file which contains permissions to all the files in your extension. This will
make it easier to start setting up permissions for your app. You can do this by simply creating an extension with
some objects as described below.

To export permission sets using Visual Studio Code


1. In Visual Studio Code, open your extension with objects; pages, reports, tables, queries, codeunits, and/or
XMLports.
2. Open the command palette using the Ctrl+Shift+P keys and select the AL: Generate permission set
containing current extension objects command.

NOTE
If you do this repeatedly, Visual Studio Code will probe for overwriting the file, there is no support for merging
manual corrections into newly generated content.

3. Publish the app.


Now, you have the XML file with default permissions to all your objects.
Example from Visual Studio Code
The following example illustrates the generated .xml file from MyProject which contains a table with objectID
50106 and two object types are generated; <ObjectType>0</ObjectType> is TableData and
<ObjectType>1</ObjectType> is Table .
NOTE
The maximum length of the RoleID attribute is 20 characters. If the RoleID exceeds this length, then the XML schema
validation fails and the corresponding permission set file is not included in the resulting app package. You will get a
warning in the Visual Studio output panel.

<?xml version="1.0" encoding="utf-8"?>


<PermissionSets>
<PermissionSet RoleID="MyProject" RoleName="MyProject">
<Permission>
<ObjectID>50106</ObjectID>
<ObjectType>0</ObjectType>
<ReadPermission>1</ReadPermission>
<InsertPermission>1</InsertPermission>
<ModifyPermission>1</ModifyPermission>
<DeletePermission>1</DeletePermission>
<ExecutePermission>0</ExecutePermission>
<SecurityFilter />
</Permission>
<Permission>
<ObjectID>50106</ObjectID>
<ObjectType>1</ObjectType>
<ReadPermission>0</ReadPermission>
<InsertPermission>0</InsertPermission>
<ModifyPermission>0</ModifyPermission>
<DeletePermission>0</DeletePermission>
<ExecutePermission>1</ExecutePermission>
<SecurityFilter />
</Permission>
</PermissionSet>
</PermissionSets>

Object type mapping


The mapping of object types in the XML such as <ObjectType>0</ObjectType> generated from Visual Studio Code
is the following:

O B JEC T T Y P E N UM B ER

TableData 0

Table 1

Report 3

Codeunit 5

XMLPort 6

Page 8

Query 9

FieldNumber 11

PageExtension 14
O B JEC T T Y P E N UM B ER

TableExtension 15

Enum 16

EnumExtension 17

Profile 18

ProfileExtension 19

See Also
Entitlements and Permission Sets Overview
Permissions on Database Objects
Permissions Property
TestPermissions Property
Entitlement Object
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

The entitlement object in Business Central describes which objects in Business Central a customer is entitled to
use according to the license that they purchased or the role that they have in AAD.
An entitlement consists of a number of PermissionSet Objects put together to constitute a set of meaningful
permissions for a user. An entitlement can only include permission set objects which reference the objects that
are included within the same app. This is to ensure that the entitlements included with one app cannot alter or
redefine the entitlements included with another app.
Entitlements can only be used with the online version of Business Central.

NOTE
In the current version of Business Central entitlements can only be included with Microsoft apps (enforced by the
AppSource cop rules and the technical validation checks that we run for the apps submitted to AppSource). These objects
will become available for the ISV apps when we introduce ability to monetize AppSource apps in one of our future
releases.

Snippet support
Typing the shortcut tentitlement will create the basic layout for an entitlement object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Entitlement examples
This example illustrates a simple entitlement object with the Type property set to Role , which means that the is
entitlement is associated with an AAD role. When Type is set to Role , the RoleType property is used to
distinguish between local and delegated assignments of the role, in this case it is Delegated . The
ObjectEntitlements property defines the list of permissions that the entitlement includes.

entitlement BC_Role_Delegated
{
Type = Role;
RoleType = Delegated;
Id = '1a2aaaaa-3aa4-5aa6-789a-a1234567aaaa';
ObjectEntitlements =
”D365 BUS PREMIUM - BaseApp”;
}

An example of an entitlement where Type is PerUserServicePlan :


entitlement BC_PerUserServicePlan
{
Type = PerUserServicePlan;
Id = '1a2aaaaa-3aa4-5aa6-789a-a1234567aaaa';

ObjectEntitlements = "D365 BASIC";

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Extension Object
Page Background Tasks
2/6/2023 • 17 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

To improve the performance of a page, you can develop the page to run read-only computations and long
processes asynchronously in background tasks. Background tasks make a page quicker to open and more
responsive, faster for users to enter information. Users aren't blocked from working while waiting for the
computations to finish. Typical places where you might use background tasks are on cues and pages in
FactBoxes.

About background tasks


When a page opens in the client, a session is established between the page and the Business Central Server
instance. Consider this session as the parent session. As a user works on the page, the user can sometimes be
blocked from continuing until a process has completed. This situation is where background tasks can be
beneficial.
A page background task is a child session that runs processes from a codeunit in the background. The user can
continue to work on the page while the task runs. It's similar to other background sessions. The difference is that
when the process completes, the child session is ended. The parent session is notified with results of the task.
Then, the client will handle the results on the Business Central Server instance.
Background task flow
A background task is a multithread operation between the parent and child sessions. The following diagram
illustrates the flow of a background task. In the illustration, the threads start in the order: THREAD A, THREAD B,
THREAD C.
Background task characteristics and behavior
A page background task has the following characteristics:
Does read-only operations; it can't write to or lock the database.
Runs on the same Business Central Server instance as the parent session.
The parameters that are passed to and returned from page background task are in the form of a
dictionary<string, string> .
Calls OpenCompany and executes in its own transaction.
The callback triggers can't execute UI operations, except notifications and control updates.
If the calling page or session closes or the current record is changed, the background task is canceled.
It has a default and maximum timeout, which cancels the task automatically.
Doesn't insert session event records; it relies on the parent session event records.
Runs isolated from the parent session. Apart from the completion and error triggers, it can't call back to the
parent session.
There's a limit on the number of background tasks per session. If there are more tasks than the threshold
specified per session, then the requests are queued.
Executed synchronously from web services.
Not counted as part of the license calculation.
Background tasks API
The API for background tasks includes the following methods and triggers:

TYPE NAME DESC RIP T IO N

Methods EnqueueBackgroundTask Creates and queues a background task


that runs the specified codeunit
(without a UI) in a child session of the
page session. If the task completes
successfully, the
OnPageBackgroundTaskComplete
d trigger is invoked. If an error occurs,
the OnPageBackgroundTaskError
trigger is invoked. If the page is closed
before the task completes, the task is
canceled.

GetBackgroundParameters Gets the page background task input


parameters.

SetBackgroundTaskResult Sets the page background task result


as a dictionary. When the task is
completed, the
OnPageBackgroundCompleted trigger
will be invoked on the page with this
result dictionary

RunPageBackgroundTask Runs the page background task


codeunit in the current session.

CancelBackgroundTask Attempt to cancel a page background


task.

Triggers OnPageBackgroundTaskCompleted Runs after a page background task has


successfully completed.

OnPageBackgroundTaskError Runs when an error occurs in a page


background task.

How to create a page background task


The following figure illustrates the application objects and code involved in creating a background task. The
code has been simplified for demonstration purposes.
The general steps are as follows:
1. Create a background task codeunit that includes the logic that you want to run in the background.
2. On the page, complete the following steps:
a. Add code that creates (or enqueues) the page background task at runtime.
b. Add code to the OnPageBackgroundTaskCompleted trigger to handle the results of the background
task and update the UI.
c. Add code to the OnPageBackgroundTaskError trigger to handle errors that occur in the background
task.
These steps are described in more details in the following sections. To help explain page background tasks, the
sections use a simple example. The example extends the Customer card page to include a page background
task. The task gets the current system time, waits a specified number of milliseconds, and gets the system time
again. The page is extended with three new fields: Star t Time , Duration , and End Time . In the page UI, these
fields are updated with results of the background task, along with a notification when the task completes.

Creating a background task codeunit


You create a codeunit that does the computations that you want to run in the background. You'll also have to
include code that collects the results of computations and passes them back to the calling page for handling.
The background task codeunit is a standard codeunit, which you create like any other codeunit, except it has the
following characteristics:
The OnRun() trigger is invoked without a record.
It can't display any UI.
It can only read from the database; not write to the database. If there's code that attempts to write to the
database at runtime, an error occurs. The error informs the user that they don't have permission to do the
operation on the table. For example, if the code tried to insert a record, an error similar to the following
message would occur: You don't have the following permissions on TableData 50125: Insert .
Casting must be manually written in code by using Format() and Evaluate() methods.
For general information about creating a codeunit, see Codeunit Object.
Getting the input parameters from the page background task
When a page background task is enqueued, it can include a set of parameters that can be used in the
computations that are done in the background task codeunit. The parameters are a collection of key and value
pairs. The parameters are passed as a dictionary of text to the codeunit's OnRun trigger when the page
background task session starts.
To get the parameters, call the GETBACKGROUNDPARAMETERS method:

Parameters := Page.GetBackgroundParameters()

Use the EVALUATE method to convert the parameters to the required data type calculations.
Defining and setting the results
The results that are computed by the codeunit must be in the form of a dictionary of text. When the codeunit
completes successfully, the results are passed to the parent session in a call to the OnPageBackgroundCompleted
trigger, which will be explained later in this article.
The basic steps for defining the results are as follows:
1. Define a variable of the data type Dictionary of [Text, Text] for holding the results.
2. Use the Add to add key-value pairs for the results to the dictionary.
3. Call the SETBACKGROUNDTASKRESULT method to set the results in the background task.

Page.SetBackgroundTaskResult(Result: Dictionary[Text, Text])

Example
In this example, the page background task codeunit is used to get the current system time. Then, after waiting a
short period of time, it gets the system time again. The waiting period is defined by an input parameter (called
Wait ) that was passed to the background task from the parent session.
codeunit 50100 PBTWaitCodeunit
{
trigger OnRun()
var
Result: Dictionary of [Text, Text];
StartTime: Time;
WaitParam: Text;
WaitTime: Integer;
EndTime: Time;
begin
if not Evaluate(WaitTime, Page.GetBackgroundParameters().Get('Wait')) then
Error('Could not parse parameter WaitParam');

StartTime := System.Time();
Sleep(WaitTime);
EndTime := System.Time();

Result.Add('started', Format(StartTime));
Result.Add('waited', Format(WaitTime));
Result.Add('finished', Format(EndTime));

Page.SetBackgroundTaskResult(Result);
end;
}

Enqueuing a background task on the page


To create a page background task, you call the ENQUEUEBACKGROUNDTASK method from the page code to run
the page background task codeunit. The basics steps are as follows:
1. Define any input parameters for the background task.
The ENQUEUEBACKGROUNDTASK method can pass parameters to the background task that can be used
as input to the task. Input parameters must have the data type Dictionary of [Text, Text] . For example,
the following code defines a Dictionary of [Text, Text] variable and adds a single key and value pair to
dictionary on the variable.

var
TaskParameters: Dictionary of [Text, Text];
begin

TaskParameters.Add('Wait', '1000');
...
end

2. Define a global variable of the data type Integer that will be used to assign the background task an
identification number.
You don't have to assign a value to this variable. The ID is assigned automatically when the background
task is enqueued.
3. Call the ENQUEUEBACKGROUNDTASK method.
First, determine where in the code that you want to call the background task from. Typically, you call the
ENQUEUEBACKGROUNDTASK method from a page trigger.
IMPORTANT
It's important that the ID of the current record of the page remains static after the ENQUEUEBACKGROUNDTASK
method call is made and while the background task is running; otherwise the task will be cancelled. For this
reason, we recommend that you don't enqueue the background task from the OnOpenPage or OnValidate
triggers. Instead, use the OnAfterGetCurrRecord trigger.

Once you've determined the location, add the following code to enqueue the background task:

CurrPage.EnqueueBackgroundTask(TaskID, CodeunitId, Parameters, Timeout, ErrorLevel)

PA RA M ET ER DESC RIP T IO N REQ UIRED

TaskId The variable that is defined for the Yes


task ID. This variable must be a
global variable.

CodeunitId The ID of the background task Yes


codeunit.

Parameters The dictionary variable that is No


defined for the input parameters to
the background task

Timeout The number of milliseconds that the No


page background task can run
before it's automatically canceled.
You can set it to run for a maximum
of 600,000 ms (10 minutes). When
the task is canceled, the
OnPageBackgroundTaskError
trigger is called.

By default, the task timeout is


controlled by the Page
Background Task Default
Timeout and Page Background
Task Max Timeout settings on the
server instance. For more
information, see Timeout.

Note: You can add code to re-


enqueue a task when an error
occurs. For more information, see
Re-enqueuing background tasks.
PA RA M ET ER DESC RIP T IO N REQ UIRED

ErrorLevel The severity level for unhandled No


errors that occur in the background
task. The severity level will
determine how the errors are shown
in the client UI. Values include:

PageBackgroundTaskErrorLevel::Ignore
specifies that errors are
ignored and have no effect
in the client.

PageBackgroundTaskErrorLevel::Warning
gives errors a severity level
of warning. Warnings appear
as a notification in the client.

PageBackgroundTaskErrorLevel::Error
gives errors a severity level
of error. Errors appear as a
notification in the client. This
value is the default.

Re -enqueuing background tasks


There are some scenarios where you want to enqueue a page background task again, after it's been initially
enqueued. For example:
You want to refresh the data on the page, like a part in a FactBox.
You want to re-enqueue a task if it times out. When a page background task exceeds the specified timeout,
the background task is canceled and an error with error code ChildSessionTaskTimeout occurs.
To re-enqueue a page background task, call the ENQUEUEBACKGROUNDTASK method on either the
OnPageBackgroundTaskCompleted or OnPageBackgroundTaskError triggers, depending on your scenario. For detailed
examples, see the PageBackgroundTask.AutoRefresh project in the BCTech GitHub repository.

NOTE
Use this pattern cautiously to avoid endless looping and applying excessive load on the server. Also, consider the Child
Sessions Max Queue Length limit of the server instance. If this limit is exceeded, enqueuing will fail.

Design considerations and limitations


The enqueued page background task stores the record ID of the current page. If the current record ID on the
page changes, or the page is closed, the task is canceled.
On list pages, it's recommended not to enqueue a page background task from OnAfterGetRecord trigger,
unless you're aware of the consequences. If you enqueue a page background task from the OnAfterGetRecord
, the task will be immediately canceled after the first row is retrieved. The reason is that the OnAfterGetRecord
trigger is called on every row. Because the record changes for each row, the page background task is
canceled when the trigger runs after the first row.
By default, only five page background tasks can be run simultaneously for a parent session. If there are more
than five, they're queued and run when a slot becomes available as other tasks finish. If you're using version
15.2 or later, you can increase or decrease this value by changing the Child Sessions Max Concurrency
setting of the server instance. You can also change the Child Sessions Max Queue Length setting to
specify the maximum number of child sessions that can be queued per parent session of a page background
task. If this value is exceeded, an error occurs. For more information, see Configuring Business Central Server
- Asynchronous Processing. the Page.Rec is different.
Example
The following example extends Customer Card page of the base application to include three fields for
displaying times that are calculated in a page background task.

pageextension 50100 CustomerCardExt extends "Customer Card"


{
layout
{
addlast(General)
{

field(starttime;starttime)
{
ApplicationArea = All;
Caption = 'Start Time';
Editable = false;
}

field(durationtime;durationtime)
{
ApplicationArea = All;
Caption = 'Duration';
Editable = false;
}

field(endtime;endtime)
{
ApplicationArea = All;
Caption = 'End Time';
Editable = false;
}
}
}

var
// Global variable used for the TaskID
WaitTaskId: Integer;

// Variables for the three fields on the page


starttime: Text;
durationtime: Text;
endtime: Text;

trigger OnAfterGetCurrRecord()
var
//Defines a variable for passing parameters to the background task
TaskParameters: Dictionary of [Text, Text];
begin
TaskParameters.Add('Wait', '1000');

CurrPage.EnqueueBackgroundTask(WaitTaskId, Codeunit::PBTWaitCodeunit, TaskParameters, 1000,


PageBackgroundTaskErrorLevel::Warning);
end;
}

Coding the background task completion trigger to handle the results


When a page background task completes successfully, the OnPageBackgroundTaskComplete trigger of the page in
the parent session is called, and the results of the task are passed to the trigger. The results are passed as a
dictionary of text. You add code to the trigger to handle the results. This operation typically includes updating
the record in the page UI with the calculated values and caching the results in the database. The
OnPageBackgroundTaskComplete trigger has the following signature:

trigger OnPageBackgroundTaskCompleted(TaskId: Integer; Results: Dictionary of [Text, Text])

PA RA M ET ER DESC RIP T IO N

TaskId The ID that is assigned to the background task.

Results The results of the background task

Design considerations and limitations


Use the value of TaskID parameter assigned by the ENQUEUEBACKGROUNDTASK method call to identify a
specific task.
The client user must have the appropriate write permission to cache results in the database.
Calling the UPDATE method has no effect in the trigger.
Except for notifications, the trigger can't render UI in the client.
Example
The following example modifies the OnPageBackgroundTaskCompleted trigger to update the page with the started
and finished times that were calculated in the page background task, and displays a notification that the times
have been updated.

trigger OnPageBackgroundTaskCompleted(TaskId: Integer; Results: Dictionary of [Text, Text])


var
started: Text;
waited: Text;
finished: Text;
PBTNotification: Notification;
begin
if (TaskId = WaitTaskId) then begin
Evaluate(started, Results.Get('started'));
Evaluate(waited, Results.Get('waited'));
Evaluate(finished, Results.Get('finished'));

starttime := started;
durationtime := waited;
endtime := finished;
PBTNotification.Message('Start and finish times have been updated.');
PBTNotification.Send();
end;
end;

Handling errors
Within the page background task flow, errors can occur in three different locations:
The page background task codeunit.

NOTE
A background task timeout will also result in an error.

The OnPageBackgroundTaskError trigger of the page.


The OnPageBackgroundTaskCompleted trigger of the page.

With errors that occur in the page background codeunit, you can control how the errors affect the client UI and
the resultant data. For example, some errors are more severe than others. Users should be notified when an
error occurs in some cases. Other times, the error can be ignored.
Errors that occur while executing the OnPageBackgroundTaskError or OnPageBackgroundTaskCompleted always
display in the client with the severity level of error ( PageBackgroundTaskErrorLevel:Error ).
Handling errors that occur in the background task
When an error occurs in the page background task codeunit, the OnPageBackgroundTaskError trigger of the page
in the parent session is automatically called with information about the error. To handle these errors, you can
either use the OnPageBackgroundTaskError trigger as-is, that is with no custom code, or you can add custom code
to the trigger to handle the errors separately.
The OnPageBackgroundTaskError trigger has the following signature:

trigger OnPageBackgroundTaskError(TaskId: Integer; ErrorCode: Text; ErrorText: Text; ErrorCallStack: Text;


var IsHandled: Boolean)

The following table describes the parameters of the trigger:

PA RA M ET ER DESC RIP T IO N

TaskId Specifies the ID assigned to the background task.

ErrorCode Specifies the error code assigned to the error that occurred
in the background task, for example, NDBCS:Deadlock or
DB:FatalCode . The error code is assigned by the Business
Central Server instance.

ErrorText Specifies the error message of the error that occurred in the
background task.

ErrorCallStack Specifies the error's call stack on the Business Central Server
instance.

IsHandled Specifies whether the error is handled. The default is false .

Using the OnPageBackgroundTaskError trigger as-is


If you want all errors that occur in the background task to be handled according to the severity level that was
specified for the background task when it was enqueued, then don't add any code to the
OnPageBackgroundTaskError trigger. In this case, the ErrorLevel parameter of the ENQUEUEBACKGROUNDTASK method
call determines how the error is handled in the client.
If the ErrorLevel is PageBackgroundTaskErrorLevel:Ignore , then error doesn't affect the client, and there's no
indication on the page that the error occurred.
If the ErrorLevel is PageBackgroundTaskErrorLevel:Warning or PageBackgroundTaskErrorLevel:Error , the error
message displays as a notification on the page. There's currently no distinction in the notification as to
whether the error is a warning or error.
For this implementation, you can either add the empty OnPageBackgroundTaskError trigger or omit the trigger
entirely.
Customizing the OnPageBackgroundTaskError trigger
When OnPageBackgroundTaskError is called, it includes information about the error, such as the error code, error
text, and call stack. You can add code to the trigger that handles errors based on this information. You do this by
using the ÌsHandled boolean variable in your code:
If IsHandled is set to true , the error thrown in the background task is ignored and handled by code that
you add in the trigger. Here, you can add code to update the UI and associated record, similar to what can be
done by OnPageBackgroundTaskCompleted trigger.
If IsHandled is set to false , which is the default, the error in the background task is displayed in the client
with the severity level that was specified by ErrorLevel parameter when the background task when was
enqueued.
Example
The following example modifies the OnPageBackgroundTaskError trigger to display a more user-friendly
notification in the client when the error Could not parse parameter WaitParam or timeout occurs in the page
background task.

trigger OnPageBackgroundTaskError(TaskId: Integer; ErrorCode: Text; ErrorText: Text; ErrorCallStack: Text;


var IsHandled: Boolean)
var
PBTErrorNotification: Notification;
begin
if (ErrorCode = 'ChildSessionTaskTimeout') then begin
IsHandled := true;
PBTErrorNotification.Message('Something went wrong. The start and finish times haven''t been updated.');
PBTErrorNotification.Send();
end

else if (ErrorText = 'Child Session task was terminated because of a timeout.') then begin
IsHandled := true;
PBTErrorNotification.Message('It took too long to get results. Try again.');
PBTErrorNotification.Send();
end
end;

Testing page background tasks


The TestPage data type includes the RUNBACKGROUNDTASK method that allows you to run unit tests for page
background task codeunit. The following code is an example of a text codeunit that uses the
RUNBACKGROUNDTASK method to test the page background task codeunit used in this article:
codeunit 50122 MyPBTCodeunit
{
Subtype = Test;
trigger OnRun()
begin
CustomerCard.OpenEdit();

// Adds the parameters to be used as input to the background task


TaskParameters.Add('Wait', '1000');

// Runs the background task codeunit


Results := CustomerCard.RunPageBackgroundTask(50100, TaskParameters);

// Returns the results in the client


Message('Start time: ' + '%1' + ', Duration :' + '%2' + ', Finished time: ' + '%3',
Results.Get('started'), Results.Get('waited'), Results.Get('finished'));
end;

var
CustomerCard: TestPage "Customer Card";

Results: Dictionary of [Text, Text];


TaskParameters: Dictionary of [Text, Text];
}

Debugging page background tasks


Like with other code in the application, you debug page background tasks by using the integrated debugger (see
Debugging). However, there are a couple limitations to be aware of:
Only one session can be debugged at a time.
If a breakpoint in a child session is hit, the child session will become the debugged session.
Other sessions will continue to run normally.
In other sessions, the breakpoints and error sessions will be ignored until the child session is completed.

Monitoring page background tasks


To monitor page background tasks, you can use the # Active child session performance counter and the event
log.
The # Active child session performance counter monitors the number of active child sessions (page
background tasks) on the Business Central Server instance.
In the event log, events that occur in the child session are recorded in the Ser ver > Admin channel log and
tagged with Session type: ChildSession . Events that occur in the parent session, such as in the
OnPageBackgroundTaskError or OnPageBackgroundTaskCompleted triggers, are tagged with Session type:
Background .

Designing part pages for page background tasks


Parts are a special category of page designed to be embedded within another page. Part type pages include
ListPart, CardPart, and HeadlinePart. Like other page types, you can design a part page to use one or more page
background tasks. However, unlike other page types, a part page won't display any data until all page
background tasks have completed. This condition applies to synchronous data that's not reliant on the
background tasks. In the user-interface, dashes (-) appear for field values while the page background tasks run.
To work around this behavior, separate the synchronous data into a separate page part.
See Also
Configuring Business Central Server - Asynchronous Processing
Business Central Performance Counters
Monitoring Business Central Server Events
Page Parts Overview
API Page Type
2/6/2023 • 2 minutes to read • Edit Online

Pages of the type API are used to create versioned, webhook-supported, OData v4 enabled REST web services.
This type of page cannot be displayed in the user interface, but is intended for building reliable integration
services. When creating this page type, you must specify a number of properties that provide information for
the web service endpoint. Use the snippet tpage - Page of type API to get the right template and the list of
these properties automatically filled in. This page type cannot be extended by creating a page extension object.
Instead, you must create a new API by adding a page object.
Pages of the type API can be used to develop a custom API. For more information, see Developing a Custom
API.

Naming conventions
For the API page type, the following naming conventions exist:
camelCase for naming attributes, tables, as well as APIPublisher, APIGroup, EntityName, and EntitySetName.
Alphanumeric characters allowed (A-Z+a-z+0-9) in above elements.
APIVersion follows the pattern vX.Y or beta.
At design time, the compiler will show warnings on casing violations and errors on naming violations. Once an
API page is deployed, the corresponding $metadata is exposed on the endpoint of the page.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Create, read, update, and delete operations


API pages support create, read, update, and delete operations. If you want to disallow create, update, and delete
operations, you can use the InsertAllowed, ModifyAllowed, and DeleteAllowed properties respectively.

Example of the API page type


The following page example publishes an API available at: ../contoso/app1/v2.0/companies({id})/customers . The
APIVersion can be specified as one version, or a list of versions, if the API is supported through multiple
versions.
page 50120 MyCustomerApi
{
PageType = API;
Caption = 'My Customer API';
APIPublisher = 'contoso';
APIGroup = 'app1';
APIVersion = 'v2.0', 'v1.0';
EntityName = 'customer';
EntitySetName = 'customers';
SourceTable = Customer;
DelayedInsert = true;

layout
{
area(Content)
{
repeater(GroupName)
{
field(id; Id)
{
Caption = 'ID';
}
field(name; Name)
{
Caption = 'Name';
}
}
}
}
}

See Also
AL Development Environment
API Query Type
Developing a Custom API
Page Extension Object
APIPublisher Property
APIGroup Property
APIVersion Property
EntityName Property
EntitySetName Property
Developing Extensions
API Query Type
2/6/2023 • 2 minutes to read • Edit Online

Queries of the type API are used to generate web service endpoints and this type of query cannot be used to
display data in the user interface. A query of the API type can be used to join data from different data sources.
The data can only be viewed. When creating this query type, you must specify a number of properties that
provide information for the web service endpoint. Use the snippet tquery - Query of type API to get the right
template and the list of these properties automatically filled in.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Example of the API query type


The following query example publishes an API available at: ../contoso/app1/v1.0/companies({id})/customerSales .
The APIVersion can be specified as one version, or a list of versions, if the API is supported through multiple
versions.
query 20000 "APIV1 - Customer Sales"
{
QueryType = API;
APIPublisher = 'contoso';
APIGroup = 'app1';
APIVersion = 'v1.0';
Caption = 'customerSales', Locked = true;
EntityName = 'customerSale';
EntitySetName = 'customerSales';

elements
{
dataitem(QueryElement1; Customer)
{
column(customerId; Id)
{
Caption = 'Id', Locked = true;
}
column(customerNumber; "No.")
{
Caption = 'No', Locked = true;
}
column(name; Name)
{
Caption = 'Name', Locked = true;
}
dataitem(QueryElement10; "Cust. Ledger Entry")
{
DataItemLink = "Customer No." = QueryElement1."No.";
SqlJoinType = LeftOuterJoin;
DataItemTableFilter = "Document Type" = FILTER (Invoice | "Credit Memo");
column(totalSalesAmount; "Sales (LCY)")
{
Caption = 'TotalSalesAmount', Locked = true;
Method = Sum;
}
filter(dateFilter; "Posting Date")
{
Caption = 'DateFilter', Locked = true;
}
}
}
}
}

See Also
AL Development Environment
API Page Type
APIPublisher Property
APIGroup Property
APIVersion Property
EntityName Property
EntitySetName Property Query Object
Developing Extensions
Implementing the Camera in AL
2/6/2023 • 3 minutes to read • Edit Online

You can access the camera of a device from the Business Central Web client in the browser and from the
Business Central Mobile App. This allows the user to take pictures and handle them directly from the same
device, and in that way, improve accuracy of capturing data closest to the source, and reduce end-to-end time to
perform tasks.
You can also add access to the camera to a specific page from the AL Language development environment. For a
Dynamics 365 Business Central existing implementation of this, see the Picture factbox on the Item Card ,
which lets you take a picture of a specific item and store it together with the item.

IMPORTANT
The camera access is only available on devices that have a camera.

Example
This example illustrates how to implement the camera capability on a page in AL. The example implements three
actions to take a picture: Take Picture , Take Picture High Quality , and Take Picture Low Quality . However,
it does not include code that saves the picture to the database.
The example also shows how to specify options for the camera functionality such as picture quality or source
type. For more information about the different options that can be set for the camera, see CameraOptions
Overview.

NOTE
To enable the camera functionality, it is required that you add the path of the folder containing the
"Microsoft.Dynamics.Nav.ClientExtensions" assembly on the Al: Assembly Probing Paths setting on the User
Settings or Workspace Settings so the compiler can access it. For more information, see Getting started with
Microsoft .NET Interoperability from AL.

The following code will create two variables; the CameraAvailable variable is a Boolean that checks whether the
current device has a camera. The Camera variable is a DotNet type that gets instantiated by adding code to the
OnOpenPage trigger. Then, it will add the actions to the page that lets the user start the camera. Finally, the trigger
Camera::PictureAvailable is defined to handle the incoming picture.

page 50101 "Card with Camera Capability"


{

Caption = 'Card Page';


PageType = Card;
RefreshOnActivate = true;
SourceTable = "Test Table";

layout
{
area(content)
{
//...
}
}
}

actions
{

area(Processing)
{
action(TakePicture)
{
Visible = CameraAvailable;
Promoted = true;
PromotedCategory = Process;
PromotedIsBig = true;
Image = Camera;

trigger OnAction()
begin
Camera.RequestPictureAsync();
end;
}

action(TakePictureHigh)
{
Visible = CameraAvailable;
Promoted = true;
PromotedCategory = Process;
PromotedIsBig = true;
Image = Camera;

trigger OnAction()
begin
CameraOptions := CameraOptions.CameraOptions();
CameraOptions.Quality := 100;
Camera.RequestPictureAsync(CameraOptions);
end;
}

action(TakePictureLow)
{
Visible = CameraAvailable;
Promoted = true;
PromotedCategory = Process;
PromotedIsBig = true;
Image = Camera;

trigger OnAction()
begin
CameraOptions := CameraOptions.CameraOptions();
CameraOptions.Quality := 10;
Camera.RequestPictureAsync(CameraOptions);
end;
}
}

trigger OnOpenPage()
begin
// The IsAvailable() enables the camera functionality based on its presence.
if Camera.IsAvailable() then begin
Camera := Camera.Create();
CameraAvailable := True;
end;
end;

// The PictureName contains the name of the file including its extension on the device.
// The naming scheme depends on the device platform.
// The PictureFilePath contains the path to the picture in a temporary folder on the server for the
current user.
// The PictureAvailable trigger handles the picture for when the camera has captured it and it has been
// The PictureAvailable trigger handles the picture for when the camera has captured it and it has been
uploaded.
trigger Camera::PictureAvailable(PictureName: Text; PictureFilePath: Text)
begin
IncomingFile.Open(PictureFilePath);
Message('Picture size: %1', IncomingFile.Len());
IncomingFile.Close();
// It is important to clean up by using the File.Erase command to avoid accumulating image files.
File.Erase(PictureFilePath);
end;

var
[RunOnClient]
[WithEvents]
Camera: DotNet UT_CameraProvider;
CameraOptions: DotNet UT_CameraOptions;
// Checks whether the current device has a camera.
CameraAvailable: Boolean;
IncomingFile: File;
}

dotnet
{
assembly("Microsoft.Dynamics.Nav.ClientExtensions")
{

type("Microsoft.Dynamics.Nav.Client.Capabilities.CameraProvider"; "UT_CameraProvider")
{

type("Microsoft.Dynamics.Nav.Client.Capabilities.CameraOptions"; "UT_CameraOptions")
{

}
}
}

For information about troubleshooting access to camera, see Troubleshooting: Camera and Location.

See Also
Getting started with Microsoft .NET Interoperability from AL
Implementing Location in AL
CameraOptions Overview
RunOnClient property
WithEvents property
Implementing Location in AL
2/6/2023 • 2 minutes to read • Edit Online

You can access the location information of a device from the Business Central Web client in the browser and
from the Business Central Mobile App. This functionality could be useful in scenarios such as calculating routes
from the current location or planning the next round of customer visits based on their addresses.
You can also add access to location information to a specific page from the AL Language development
environment. For a Dynamics 365 Business Central existing implementation of this, see the Show On Map link on
the Customer Card , which displays a map that shows where your customer is located based on the GPS
coordinates and gives directions to reach its location.

IMPORTANT
Location information is only available on devices that are able to obtain location coordinates, such as using GPS
capabilities.

Example
This example illustrates how to implement the location capability on a page in AL. The example implements a
GetLocation action on a page that returns the coordinates of the current customer's address, but does not save
this information to the database.
The example also shows how to specify options for the location functionality such as setting a timeout or
enabling high accuracy. For more information about the different options that can be set for location, see
LocationOptions Overview.

NOTE
To enable the location functionality, it is required that you add the path of the folder containing the
"Microsoft.Dynamics.Nav.ClientExtensions" assembly on the Al: Assembly Probing Paths setting on the User
Settings or Workspace Settings so the compiler can access it. For more information, see Getting started with
Microsoft .NET Interoperability from AL.

The following code will create two variables; the LocationAvailable variable is a Boolean that checks whether
the current device has location capabilities. The Location variable is a DotNet type that gets instantiated by
adding code to the OnOpenPage trigger. Then, it will add an action to the page that lets the user retrieve the
location information. Finally, the trigger Location::LocationChanged is defined to handle the incoming location
information.

page 50101 "Card with Location Capability"


{

Caption = 'Card Page';


PageType = Card;
RefreshOnActivate = true;
SourceTable = "Test Table";

layout
{
area(content)
{
{
//...
}
}

actions
{
area(Processing)
{
action(GetLocation)
{
Visible = LocationAvailable;
Promoted = true;
PromotedCategory = Process;
PromotedIsBig = true;
Image = Map;

trigger OnAction()
begin
LocationOptions := LocationOptions.LocationOptions;
LocationOptions.EnableHighAccuracy();
Location.RequestLocationAsync();
end;
}
}

trigger OnOpenPage()
begin
if Location.IsAvailable() then begin
Location := Location.Create();
LocationAvailable := true;
end;
end;

trigger Location::LocationChanged(Location: DotNet Location)


begin
// Location.Status can be:
// 0 = Available
// 1 = NoData (no data could be obtained)
// 2 = TimedOut (location information not obtained in due time)
// 3 = NotAvailable (for example user denied app access to location)
if Location.Status = 0 then
Message('Your position: %1 %2', Location.Coordinate.Latitude, Location.Coordinate.Longitude)
else
Message('Position not available');
end;

var
[RunOnClient]
[WithEvents]
Location: DotNet LocationProvider;
LocationAvailable: Boolean;
LocationOptions: DotNet UT_LocationOptions;
}

dotnet
{
assembly("Microsoft.Dynamics.Nav.ClientExtensions")
{

type("Microsoft.Dynamics.Nav.Client.Capabilities.LocationProvider"; LocationProvider)
{

type("Microsoft.Dynamics.Nav.Client.Capabilities.Location"; Location)
{
}

type("Microsoft.Dynamics.Nav.Client.Capabilities.LocationOptions"; UT_LocationOptions)
{

}
}
}

For information about troubleshooting access to location information, see Troubleshooting: Camera and
Location.

See Also
Getting started with Microsoft .NET Interoperability from AL
LocationOptions Overview
Troubleshooting: Camera and Location
Implementing the Camera in AL
RunOnClient property
WithEvents property
Preprocessor Directives in AL
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

In AL, like in other programming languages, preprocessor directives can be used to make code conditional, to
suppress warnings, or to enable the ability to expand and collapse in code. Preprocessor directives can be
divided into the following groups. For more information about each type, use the links provided in the following
section.
Conditional directives
Regions
Pragmas
Any code can be made conditional, including table fields, and checked using a conditional directive. To check
code using a conditional directive, you must define a symbol to check. A symbol returns a boolean value; true
or false . Symbols can be defined at the beginning of a source file and the scope of the specific symbol is the
file that it's defined within. You can also define symbols in the app.json file, and then the scope is global for the
extension.

NOTE
Built-in symbols are currently not supported in AL. Symbols must be defined in a specific file or in the app.json file.

NOTE
User personalization and profile configuration (including profile copy) are not meant to work with directives, which means
that they are ignored by the platform in the cases of #pragma, #region, #endregion and fail with an error when they are
not supported for #if, #elif, #define, etc.

Conditional directives
The following conditional preprocessor directives are supported in AL.

C O N DIT IO N A L P REP RO C ESSO R DIREC T IVE DESC RIP T IO N

#if Specifies the beginning of a conditional clause. The #endif


clause ends it. Compiles the code between the directives if
the specified symbol being checked is defined.

#else Specifies a compound conditional clause. If none of the


preceding clauses evaluate to true , the compiler will
evaluate code between #else and #endif .

#elif Combines else and if . If #elif is true the compiler


evaluates all code between #elif and the next conditional
directive.
C O N DIT IO N A L P REP RO C ESSO R DIREC T IVE DESC RIP T IO N

#endif Specifies the end of a conditional clause that begins with


#if .

#define Defines a symbol that can be used to specify conditions for a


compilation. For example, #define DEBUG . The scope of the
symbol is the file that it was defined in.

#undef Undefines a symbol.

Defining preprocessorSymbols
Symbols can be defined globally in the app.json file. A symbol can also be defined using the #define directive
in code, but if symbols are defined in the app.json file, they can be used globally. The following example defines
DEBUG as a global symbol. This can then be used from code as illustrated in the following Conditional code
example. A symbol has a boolean value that means it evaluates to true or false .
The app.json syntax is:

"preprocessorSymbols": [name [,name2]]

For example:

"preprocessorSymbols": [ "DEBUG","PROD"]

For more information, see JSON Files.

Example
#if DEBUG
trigger OnOpenPage()
begin
Message('Only in debug versions');
end;
#endif

See Also
Development in AL
AL Development Environment
Conditional directives
Region Directive in AL
Pragma Directive in AL
Deprecating Explicit and Implicit With Statements
Best Practices for Deprecation of Code in the Base App
ObsoleteState Property
ObsoleteReason Property
ObsoleteTag Property
Obsolete Attribute
Region Directive in AL
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

Region
The #region directive is used to mark a block of code that you can expand or collapse. This can, for example, be
useful for larger files for better readability or for focusing on code that you're currently working on. The
#endregion specifies the end of a #region block of code.

NOTE
On the first line of the #region a text comment can be added to describe the purpose of the block of code, see the
following example.

Syntax
#region [comment]
code

#endregion

Remarks
A #region block must be terminated with a #endregion directive.
A #region block can't overlap with an #if block. However, a #region block can be nested in an #if block,
and an #if block can be nested in a #region block.

Example
In this example, the #region directive makes a code block that is up for refactoring collapsible.

#region Ugly code - let's not look at this


procedure UglyCode()
begin
// No one should look at this
end;
#endregion

See Also
Development in AL
AL Development Environment
Pragma Directive in AL
Conditional directives
Deprecating Explicit and Implicit With Statements
Pragma Directive in AL
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

Pragma
The #pragma directive gives the compiler special instructions for the compilation of the file in which it appears.
The #pragma directive has many actions that can be used with the pragma instructions in the following sections,
which are disable , restore , and enable .
AL supports the following pragma instructions:
Pragma ImplicitWith
Pragma Warning

See Also
Development in AL
AL Development Environment
Region Directive in AL
Conditional directives
Deprecating Explicit and Implicit With Statements
AL Development Environment
2/6/2023 • 2 minutes to read • Edit Online

This section describes all of the objects that are available with the AL Language development environment for
Dynamics 365 Business Central.

TIP
If you are looking for the C/SIDE documentation, visit our Dynamics NAV library.

Defining the AL data model


TO SEE

Learn about how to define new table objects for your Table Object
extension.

Learn about how to modify and extend existing table Table Extension Object
objects.

Presenting the AL data


TO SEE

Learn about how to create new page objects for your Page Object
extension.

Learn about how to modify and extend existing page Page Extension Object
objects.

Learn about how to create page customization objects. Page Customization Object

Learn about how to create profile objects. Profile Object

Learn about how to create report objects. Report Object

Learn about how to create report extension objects. Report Extension Object

Learn about how to create xmlport objects. XmlPort Object

Learn about how to create query objects. Query Object

Learn about how to create control add-in objects. Control Add-In Object

Controlling access to data


TO SEE

Learn about how to create entitlement objects. Entitlement Object

Learn about how to create permissionset objects. Permissionset Object

Learn about how to create permissionset extension objects. Permissionset Extension Object

Writing AL code
TO SEE

Learn about writing codeunits for your extension. Codeunit Object

Get an overview of methods in AL grouped by the data type Data Types and Methods in AL
that they support.

Get an overview of method attributes in AL in alphabetical Method Attributes


order.

Get an overview of option types in AL in alphabetical order. Option Types

Get an overview of properties in AL grouped by the objects Properties Overview


that they support.

Get an overview of triggers in AL grouped by the objects Triggers Overview


that they support.

See Also
Developing Extensions
Get Started with AL
FAQ for Developing in AL
AL Language Extension Configuration
Programming in AL
2/6/2023 • 2 minutes to read • Edit Online

AL is the programming language that is used for manipulating data such as retrieving, inserting, and modifying
records in a Dynamics 365 Business Central database. It controls the execution of the various application objects,
such as pages, reports, or codeunits.
With AL, you can create business rules to ensure that the data, which is stored in the database is meaningful and
consistent with the way customers do business. Through AL programming, you can:
Add new data or transfer data from one table to another, for example, from a journal table to a ledger table.
Combine data from multiple tables into one report or display it on one page.

Where to write AL code


Almost every object in Dynamics 365 Business Central contains triggers where you can add your AL code.
Triggers exist for the following objects:
Tables and table extensions
Table fields
Pages and page extensions
Reports
Data items
XMLports
Queries
You can initiate the execution of your AL code from the following ways:
Actions
Any object that has an instantiation of the object that contains AL code. An example of an instantiation is a
variable declaration.

NOTE
If the AL code is in a local method, then you cannot run it from another object.

Variable declarations
Variables in AL are declared using the var keyword, and the syntax looks like this:

var
myInt: Integer;

If you have multiple variables of the same type, these can be declared in one line, such as:

var
myInt, nextInt, thirdInt : Integer;
isValid, doCheck : Boolean;
The protected keyword can be used to make variables accessible between tables and table extensions and
between pages and page extensions. For more information, see Protected Variables.

Guidelines for placing AL code


We recommend the following guidelines for AL code:
In general, write the code in codeunits instead of on the object on which it operates. This promotes a
clean design and provides the ability to reuse code. It also helps enforce security. For example, typically
users don't have direct access to tables that contain sensitive data, such as the General Ledger Entr y
table, nor do they have permission to modify objects. If you put the code that operates on the general
ledger in a codeunit, give the codeunit access to the table, and give the user permission to run that
codeunit. This way, security of the table won't be compromised and the user will be able to access the
table.
If you must put code on an object instead of in a codeunit, then put the code as close as possible to the
object on which it operates. For example, put code that modifies records in the triggers of the table fields.

Reusing code
Reusing code makes developing applications both faster and easier. More importantly, if you organize your AL
code as suggested, your applications will be less prone to errors. By centralizing the code, you won't
unintentionally create inconsistencies by performing the same calculation in many places, for example, in
several triggers that have the same table field as their source expression. If you have to change the code, you
could either forget about some of these triggers or make a mistake when you modify one of them.

See Also
Simple Statements
Control Statements
Methods
System-Defined Variables
Developing Extensions
Get Started with AL
FAQ for Developing in AL
2/6/2023 • 2 minutes to read • Edit Online

This topic contains a number of frequently asked questions and answers to these questions.

How do I get started?


For an overview of developing apps for Dynamics 365 Business Central, see aka.ms/GetStartedWithApps
Next, follow the Get Started with AL to set up the tools.

Which version of the AL Language extension should I use?


For Dynamics 365 Business Central cloud sandboxes you must use the AL Language extension available in the
Visual Studio Code Marketplace.
For the latest Developer Preview releases you must use the AL Language extension that is available in the next
major artifact through the "Ready! for Dynamics 365 Business Central" program on Microsoft Collaborate.

How do I enable the debugger?


To read about enabling debugging in AL, see here Debugging. To read about snapshot debugging, see Snapshot
Debugging.

Where do I find help regarding AppSource validation and submission?


When submitting an app for AppSource, you must make sure that it validates against the Technical Validation
Checklist. For frequently asked questions, see Technical Validation Checklist FAQ.

What constitutes the identity of an app?


To read about app identity and why it is important to keep certain settings for an app unchanged, see App
Identity.

File APIs are not available in Extensions V2. What do I do?


Code that relies on temporary files must be rewritten to rely on InStream and OutStream types. Code that relies
on permanent files must be rewritten to use another form of permanent storage.

DotNet types are not available in Extensions V2. What now?


For cloud solutions .NET interop is not available due to safety issues in running arbitrary .NET code on cloud
servers.
With the AL Language extension, you can find AL types that replace the most typical usages of .NET like HTTP,
JSON, XML, StringBuilder, Dictionaries, and Lists. Many .NET usages can be replaced directly by the AL types
resulting in much cleaner code. For more information, see HTTP, JSON, TextBuilder, and XML API Overview.
For things that are not possible to achieve in AL code, the recommendation is to use Azure Functions to host the
DLL or C# code previously embedded and call that service from AL.
Extensions published from Visual Studio Code or created using
Designer have disappeared from a sandbox environment. Why?
Extensions that have been published to a sandbox environment from Visual Studio Code or created using
Designer are removed when the sandbox environment is updated or relocated within our service. However, the
data of an app is not removed, so you only have to re-publish and install the app to make it available.
If you have per-tenant extensions (PTEs) installed that depend on extensions published from Visual Studio Code,
the per-tenant extensions will be removed too.
For more information, see Sandbox Environments.

Can I create something similar to Menusuites?


In the AL Language extension, the concept of Menusuites is not supported. The two primary purposes of
Menusuites are:
Making pages searchable
Making pages accessible through a navigation structure
The first purpose can be achieved in Extensions by using the new properties added to Pages and Reports. For
more information, see Adding Pages and Reports to Search.
The second purpose can be achieved by extending the Navigation Pane page and/or by adding Actions to other
existing pages that can serve as a navigation starting point. For more information, see Adding Menus to the
Navigation Pane.

How do I upgrade Extensions V1 to Extensions V2?


For information on upgrading, see the following topics: Upgrading Extensions v2 and Converting from
Extensions v1 to Extensions v2.

See Also
Get Started with AL
Keyboard Shortcuts
AL Development Environment
AL Simple Statements
2/6/2023 • 5 minutes to read • Edit Online

AL simple statements are single-line statements that are executed sequentially and don't alter the flow of code
execution. This article explains some of the simple statements in AL.

Assignment statements
Assignment statements assign a value to a variable. The value that you assign to the variable is an AL
expression. It can be a constant or a variable, or it can consist of multiple elements of AL expressions. If you use
a method call as the value to assign to a variable in an assignment statement, then the value that is assigned is
the return value of the method.
You use the ":=" operator for assignment statements.
Example
The following example assigns a constant integer value to a variable that you've defined.

Count := 1;

Example
The following example assigns a value that consists of a constant, an operator, and a variable.

Amount := 2 * Price;

Example
The following example assigns the return value of the Open Method (File) to a Boolean variable that you've
defined.

NOTE
This method is supported only in Business Central on-premises.

OK := TestFile.Open('C:\temp\simple.xml');

The return value of the Open method is optional. If you don't handle the return value in your code, then a run-
time error occurs when a method returns false . The following example causes a run-time error if the file
C:\temp\simple.xml can't be opened.

TestFile.Open('C:\temp\simple.xml');

You can handle the return value by using an if-then statement.


if TestFile.Open('C:\temp\simple.xml') then begin
// continue running
else
Error(Text001);

Example
If you want to perform arithmetic operations on a variable and then assign the result to the same variable, you
can use the following syntax.

Counter := 0;

// you can use this syntax

// for addition
Counter += 1;
// for subtraction
Counter -= 1;
// for multiplication
Counter *= 1:
// for division
Counter /= 1;

// instead of
Counter := Counter + 1;

The following example shows how to use this syntax on variables of the Text Data Type.

String := "Hello ";


String += "World";

Method statements
You use method statements to run either built-in system methods or user-defined (custom) methods. Method
calls may include parameters, which are passed to the method. For more information, see Calling Methods.

AssertError statements
You use AssertError statements in test methods to test how your application behaves under failing conditions.
The AssertError keyword specifies that an error is expected at run time in the statement that follows the
AssertError keyword.

If a simple or compound statement that follows the AssertError keyword causes an error, then execution
successfully continues to the next statement in the test method. You can get the error text of the statement by
using the GetLastErrorText method.
If a statement that follows the AssertError keyword doesn't cause an error, then the AssertError statement
causes the following error and the test method that is running produces a FAILURE result:

TestAsserterrorFail: FAILURE

An error was expected inside an AssertError statement.

Example
To create a test method to test the result of a failure of a CheckDate method that you've defined, you can use the
following code. This example requires that you create a method called CheckDate to check whether the date is
valid for the customized application.

InvalidDate := 19000101D;
InvalidDateErrorMessage := Text001;
AssertError CheckDate(InvalidDate);

IF GetLastErrorText <> InvalidDateErrorMessage then


Error('Unexpected error: %1', GetLastErrorText);

This example requires the following variables.

var
InvalidDate : Date;
InvalidDateErrorMessage : Text;
Text001 : Label 'The date is outside the valid date range.';

With statements (to be deprecated)


IMPORTANT
Using the with statement is being deprecated with Dynamics 365 Business Central 2020, release wave 2. With this
release it is a warning, which will become an error in a future release.
Using with statements introduces possible uniqueness collisions when multiple extensions contribute to the same
objects because it allows working with members using just simple names instead of qualifying them. To avoid this going
forward, we are marking the use of with , be it implicit or explicit as warnings. With this release, you can use a quick
action to fix these files, as well as suppress obsolete warnings for now. Code that contains with statements will, however,
need to be refactored before with statements are compiled with errors. For more information, see Deprecating Explicit
and Implicit With Statements. For information about using directives in code, see Directives in AL and Pragma ImplicitWith
Directive in AL.

The following syntax shows a with-do statement.

with <Record> do
<Statement>

When you work with records, addressing is created as record name, dot (period), and field name:
<Record>.<Field>
If you work continuously with the same record, then you can use with statements. When you use a with
statement, you can only specify the record name one time.
Within the scope of <Statement>, fields in <Record> can be addressed without having to specify the record
name.
You can nest several with statements. If you have identical names, then the inner with statement overrules the
outer with statement.
Example
This example shows two ways to write the same code that creates a record variable that you can commit later.
CustomerRec."No." := '1234';
CustomerRec.Name := 'Windy City Solutions';
CustomerRec."Phone No." := '555-444-333';
CustomerRec.Address := '1241 Druid Avenue';
CustomerRec.City := 'Windy City';
Message('A variable has been created for this customer.');

This example requires the following variables.

var
CustomerRec : Record Customer;

The following example shows another way to create a record variable that you can commit later:

with CustomerRec do begin


"No." := '1234';
Name := 'Windy City Solutions';
"Phone No." := '555-444-333';
Address := '1241 Druid Avenue';
City := 'Windy City';
Message('A variable has been created for this customer.');
end;

Programming conventions
Within with-do blocks, don't repeat the name of the object by using the member variable or method.
If you nest a with-do block within another explicit or implicit with-do block, then the with-do block that you
create within another with-do block must always be attached to a variable of the same type as the variable that
is attached to the surrounding with-do block. Otherwise, it can be difficult to see what variable that a member
variable or method refers to. For example, implicit with-do blocks occur in table objects and in pages that have
been attached to a record.
Example
The following example demonstrates nested with-do blocks. Both with-do blocks are attached to a Customer
Ledger Entry record variable.

with CustLedgEntry do begin


Insert;
...;
with CustLedgEntry2 do begin
Insert;
...;
end;
end;

Incorrect example
The following example demonstrates incorrect code in which you can't directly tell which record variable that the
MyField field refers to.

with CustLedgEntry do begin


...;
with VendLedgEntry do begin
MyField := <Some Value>;
...;
end;
end;
See Also
Control Statements
Methods
Directives in AL
AL Essential Methods
AL Control Statements
2/6/2023 • 13 minutes to read • Edit Online

AL code consists of one or more statements, which are executed sequentially in a top-down order. However,
you'll often need to control the direct top-down flow of the execution. One or more statements may have to be
repeated more than once, or you may have to make the execution of a certain statement conditional. To do so,
you use control structures.
The control structures in AL are divided into the following main groups, as described in this article:
AL Compound Statements
AL Conditional Statements
AL Repetitive Statements

NOTE
In the following sections, conventions for how to structure and align AL code are presented to introduce best practices. In
many cases, the structure isn't necessary to get the code to compile, but rather to improve readability.

AL compound statements
In some cases, the AL syntax only lets you use a single statement. However, if you have to run more than one
simple statements, the statements can be written as a compound statement by enclosing the them between the
begin and end keywords.

begin
<Statement 1>;
<Statement 2>;
..
<Statement n>;
end;

The individual statements are separated by a semicolon. In AL, a semicolon is used to separate statements and
not to terminate them, as in other programming languages. Nevertheless, an extra semicolon before an end
doesn't cause an error because it's interpreted by the compiler as an empty statement.

Blocks
The begin-end structure is also called a block. Blocks can be useful to refer to the other control structures in AL.
When begin follows, then, else, or do should be on the same line and preceded by one space character.
Example

if (x = y) and (a = b) then begin


x := a;
y := b;
end;

Example
if (xxx = yyyyyyyyyy) and
(aaaaaaaaaa = bbb)
then begin
x := a;
x := y;
a := y;
end else begin
y := x;
y := a;
end;

AL conditional statements
You use conditional statements to specify a condition and one or more commands to execute if the condition is
evaluated as true or false. There are two types of conditional statements in AL:
if-then-else, where there are two choices
case, where there are more than two choices
If-then-else statements
if-then-else statements have the following syntax.

if <Condition> then
<Statement1>
[else
<Statement2>]

If <Condition> is true, then <Statement1> is executed. If <Condition> is false, then <Statement2> is executed.
The square brackets around else <Statement2> mean that this part of the statement is optional. The else
statement is used when different actions are executed depending on how <Condition> is evaluated.
You can build more complex control structures by nesting if-then-else statements. The following example is a
typical if-then-else statement.

if <Condition1> then
if <Condition2> then
<Statement1>
else
<Statement2>

If <Condition1> is false, then nothing is executed. If <Condition1> and <Condition2> are both true, then
<Statement1> is executed. If <Condition1> is true and <Condition2> is false, then <Statement2> is executed.

NOTE
A semicolon in front of an else statement is not allowed.

Reading several nested if-then-else statements can be confusing but generally, an else statement belongs to the
last if statement that lacks an else statement.
Programming conventions
if and then should be on the same line, else should be on a separate line.
If there are many or long expressions, then should be on a new line and be aligned with if .
When you write if expressions with then and else parts, write them so that the then result is more
probable than the else one.
If the last statement in the then part of an if-then-else statement is an exit or an error , don't
continue with an else statement.
Example

if x = y then
x := x + 1
else
x := -x - 1;

Example

if (xxxxxxxxxx = yyy) and


(aaa = bbbbbbbbbb)
then
x := a
else
y := b;

Example

if x <> y then
exit(true);
x := x * 2;
y := y - 1;

Incorrect example

if x < y then
exit(true)
else begin
x := x * 2;
y := y - 1;
end;

Example
The following example shows an if-then statement without the optional else statement.

if Amount < 1000 then


Total := Total + Amount;

Example
The following example shows a nested if-then-else statement.

...
if Amount < 1000 then begin
if I > J then
Max := I
else
Max := J;
Amount := Amount * Max;
end;
else
...
Case statements
Case statements have the following syntax.

case <Expression> of
<Value set 1>:
<Statement 1>;
<Value set 2>:
<Statement 2>;

<Value set n>:


<Statement n>;
[else
<Statement n+1>]
end;

In this definition, the result of <Expression> is matched against each value set and <Value set> must be an
expression or a range.

NOTE
<Expression> cannot be an application object variable, since application objects don't have a comparator.

Case statements are also called multiple option statements and are typically used when you must choose
between more than two different actions. The method of the case statement is as follows:
The <Expression> is evaluated, and the first matching value set executes the associated statement, if
there's one.
If no value set matches the value of the expression and the optional else part has been omitted, then no
action is taken. If the optional else part is used, then the associated statement is executed.
The data type of the value sets must be the same as the data type of <Expression> or at least be convertible to
the same data type.
In most cases, the data type of the value sets is converted to the data type of the evaluated expression. The only
exception is if the evaluated expression is a Code variable. If the evaluated expression is a Code variable, then
the value sets aren't converted to the Code data type.

NOTE
This type conversion can cause an overflow at run time if the resulting data type cannot hold the values of the datasets.

For more information about Code variables, see Code Data Type.
Programming conventions
When you use a case statement, indent the value sets by four character spaces. If you've two or more value sets
on the same line, then separate them by commas without spaces. The last value set on a line is immediately
followed by a colon without a preceding space. The action starts on the line after the value set and is further
indented by four character spaces. If there's a begin, then it should be put on a separate line unless it follows
else. If a begin follows an else, then it should be on the same line as else.
If there are more than two alternatives, use a case statement. Otherwise, use an if-then-else statement.
Example
case Field of
Field::A:
begin
x := x + 1;
y := -y - 1;
end;
Field::B:
x := y;
Field::C,Field::D:
y := x;
else begin
y := x;
a := b;
end;
end;

Example
The following AL code prints various messages depending on the value of Number. If the value of Number
doesn't match any of the entries in the case structure, then the else entry is used as the default.

case Number of
1,2,9:
message('1, 2, or 9.');
10..100:
message('In the range from 10 to 100.');
else
message('Neither 1, 2, 9, nor in the range from 10 to 100.');
end;

Example
The following AL code shows how value sets in a case statement are evaluated if the expression is a Code data
type.

MyCode := 'ABC';
case MyCode of
'abc':
message('This message is not displayed.');
'def':
message('This message is not displayed.');
else
message('The value set does not match the expression.');
end;

This example requires that you create the following code data type variable.

var
MyCode : Code[10];

The value set 'abc' isn't converted because the evaluated expression MyCode is a code variable.

AL repetitive statements
A repetitive statement is also known as a loop. The following table shows the looping mechanisms in AL.

LO O P IN G M EC H A N ISM DESC RIP T IO N


LO O P IN G M EC H A N ISM DESC RIP T IO N

for Repeats the inner statement until a counter variable equals


the maximum or minimum value specified.

foreach Repeats the inner statement for each statement in a List,


XmlNodeList, XmlAttributeCollection, or JsonArray.

while Repeats the inner statement as long as the specified


condition is true . The statement in a loop of this kind is
repeated zero or more times.

repeat Repeats the inner statements until the specified conditions


evaluate to true . The statements in a loop of this kind are
always executed at least one time.

For-to and for-downto control structure


The following syntax shows the for-to and for-downto statement.

for <Control Variable> := <Start Number> to <End Number> do


<Statement>

for <Control Variable> := <Start Number> downto <End Number> do


<Statement>

The data type of <Control Variable> , <Start Number> , and <End Number> must be Boolean, number, time, or
date.
Use for-to and for-downto statements when you want to execute code for a specific number of times. The
<Control Variable> controls the number of times that the code of the inner statement is executed according to
the following:
In a for-to loop statement, the <Control Variable> value is increased by one after each iteration. The
inner <Statement> is executed repeatedly until the *<Start Number> * value is greater than the
*<End Number>* value.

In a for-downto loop statement, the <Control Variable> value is decreased by one after each iteration.
The inner <Statement> is executed repeatedly until the <Start Number> value is less than the
<End Number> value.

NOTE
When the for statement is executed, <Start Number> and <End Number> are converted to the same data type as
<Control Variable> if it's required. This type conversion can cause a run-time error.

NOTE
If the value of the <Control Variable> is changed inside the for loop, then the behavior is not predictable.
Furthermore, the value of the <Control Variable> is undefined outside the scope of the for loop.

Example 1
The following code initiates a for loop that uses the integer control variable named Count.
for Count := 1000 to 100000000000000 do

This example requires the following Integer data type variable.

var
Count : Integer;

When this statement is executed, then a run-time error occurs because the start, and end values are converted
to the same data type as the Count control variable. Count has been declared as an integer variable. The end
number 100000000000000 is outside the valid range for integers, and an error occurs.
Example 2
The following example shows how to nest for statements.
Set the Dimensions property of variable A to 5;7.
The following for statements could be used to initialize every element in a 5x7 array with the value 23.

for I := 1 to 5 do
for J := 1 to 7 do
A[I,J] := 23;

This example requires the following Integer data type variables.

var
I : Integer;
J : Integer;

Foreach control structure


You can use the foreach statement to iterate through List, XmlNodeList, XmlAttributeCollection, and JsonArray
expressions. The foreach statement has the following syntax.

foreach <Element> in <List> do


<Statement>

The <List> variable must be of the List, XmlNodeList, XmlAttributeCollection, or JsonArray type. The <Element>
variable must be a data type that is compatible with elements specified by the <List> .
The following code example iterates through a list of customer names and returns each customer name in a
message.

procedure PrintCustomerNames(customerNames : List of [Text]);


var
customerName : Text;
begin
foreach customerName in customerNames do
message(customerName);
end;

While -do control structure


The following syntax shows the while-do statement.
while <Condition> do
<Statement>

If <Condition> is true, then <Statement> is executed repeatedly until <Condition> becomes false. If
<Condition> is false from the start, then <*Statement> is never executed.
The while do statement can be used when some code should be repeated as long as an expression is true.
Programming conventions
When there's only one condition, put while and do on the same line. Put the statements on separate lines and
indented by two spaces.
When there are multiple conditions, put the conditions on separate lines, and indented by two spaces and put
do on a separate line that is aligned with while .

Example

while <expr> do
<Statement>;

Example

while <expr> do begin


<Statement>;
<Statement>;
end;

Example

while <expr> and


<expr> and
<expr>
do begin
<Statement>;
<Statement>;
end;

Example
The following AL code increases the variable I until it equals 1000 and displays a message when it's finished.

while I < 1000 do


I := I + 1;
message(format(I));

This example requires the following integer data type variable.

var
I : integer

Repeat-until control structure


The following syntax shows the repeat-until statement.

repeat
<Statements> until <Condition>
<Statements> is executed repeatedly until <Condition> is true.
The repeat until control structure resembles the while control structure. The difference is that because the
repeat until statement is executed from left to right, the <Statements> is always executed at least one time,
regardless of what the <Condition> is evaluated to. This contrasts with the while control structure, which
performs the evaluation before the <Statement> is executed. In the while control structure, if the first
evaluation of <Condition> returns false, then no statements are executed.
Programming conventions
Always put repeat on a separate line.
Example

if x < y then begin


repeat
x := x + 1;
a := a - 1;
until x = y;
b := x;
end;

Example
This code uses a repeat-until loop to count the number of entries in the Customer table.

Count := 0;
if Customer.find('-') then
repeat
Count := Count + 1;
until Customer.next <= 0;
message('The Customer table contains %1 records.',Count);

This example requires the following variables.

var
Count : Integer;
Customer : Record Customer;

The find method finds the first entry in the table. Each time NEXT is called, it steps one record forward. When
NEXT equals 0, there are no more entries in the table. The loop is exited, and a message displays how many
entries were found.
Exit statement
The exit statement is used to control the flow of the execution. The following syntax shows an exit statement.

exit([<Value>])

An exit statement is used to interrupt the execution of an AL trigger. The interruption occurs even when the code
is executed inside a loop or a similar structure. The exit statement is also used when a local method should
return a value.
Using exit without a parameter in a local method corresponds to using the parameter value 0. The AL method
will return the value 0 or '' (empty string).
A compile-time error occurs if exit is called by using a return parameter from either:
System-defined triggers, or
Local methods that don't return a value.
Example
The following example shows the use of the exit statement in a local method. Assume that the if statement is
used to detect an error. If the error condition is met, then execution is stopped and the local method returns the
error code 1.

for I := 1 to 1000 do begin


if Amount[I] < Total[I] then
exit(1);
A[I] := Amount[I] + Total[I];
end;

Break statement
You use the break statement to terminate the iterative statement in which it appears.

break;

You typically use the break statement in the repeating statements such as for , while , or repeat to stop an
iteration or loop when certain conditions are met.

NOTE
The break statement is different than the Break Method (Report, XMLport). Although both stop an iteration or loop, the
break method will also terminate the trigger in which it's run.

Example
The following AL code increases the variable I by one for each iteration, and terminates the iteration when I
equals 10.

while Count < 1000 do


begin
Count := Count + 1;
message(FORMAT(Count));
if Count = 10 then
break;
end;
end;

This example requires the following integer data type variable.

var
I : integer

See Also
Programming in AL
AL Simple Statements
Directives in AL
AL Essential Methods
AL Complex Types
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

With the latest version of Business Central, it's possible to return most types from procedures - both user-
defined types and most built-in types.
The method in the example below, will take a name, and return the first customer record that matches the name.
The signature specifies the return type at the end of the procedure declaration, and the procedure exits by
returning the found customer record.

///<summary>
/// Getthefirstcustomerwithnamestartingwith<paramref name="Name"/>
///</summary>
///<param name="Name">Namefilter</param>
///<returns>Firstcustomer</returns>

procedure GetCustomerByName(Name: Text): record Customer;


var
Customer: record Customer;
begin
Customer.SetFilter(Name, '@' + Name + '*');
Customer.FindFirst();
exit(Customer);
end;

It's also possible to use a named return value. Internally, the exit-statement as seen in the example above causes
an assignment to an allocated return value. The assignment will have a small performance cost based on the
type. Since the record type is treated as a value-type, it's better.

procedureGetCustomerByName(Name:Text) Customer:recordCustomer;
begin
Customer.SetFilter(Name,'@'+Name+'*');
Customer.FindFirst();
end;

The method GetCustomerByName() returns a Customer record. It can be used as you would expect in the
following example.

//Getthe firstcustomerwithnamestartingwith'spo'

Customer:=GetCustomerByName('spo');

The returned value doesn't have to be used in an assignment statement. It can be used as part of an expression
like in the following example.

//Use the returned value as an expression.

DoSomethingWithSales(GetCustomerByName('spo').GetSalesLCY());

It doesn't only work for user-defined types like records, codeunits, etc., but also for built-in types. For example,
when using the HttpClient Data Type, it's possible to write code as illustrated below.

///<summary>
///Returnsabing-readyHttpClient
///</summary>
///<returns>BingHttpClient</returns>
procedure GetBingClient() Result: HttpClient;
begin
Result.SetBaseAddress('https://www.bing.com');
end;

///<summary>
///Gettheresponsefromarequesttobing.
///</summary>
///<returns>Theresponsemessage</returns>

procedure GetBingResponse() Response: HttpResponseMessage


begin
GetBingClient().Get('', Response)
end;

///<summary>
///Gettheresponsefromwww.bing.comasanhtml-string.
///</summary>
///<returns>stringwithhtml</returns>
procedure GetBingHtml() Result: Text;
begin
GetBingResponse().Content().ReadAs(Result);
end;

See Also
Programming in AL
AL Simple Statements
Directives in AL
AL Essential Methods
HttpClient Data Type
AL Error Handling
2/6/2023 • 2 minutes to read • Edit Online

The AL language has many error handling features, which can help you deal with unexpected situations that
occur when code is run. This section contains articles about using these methods in AL to handle errors that
occur during code execution, while making sure that your application has a consistent user interface.
The following articles introduce error handling in AL:
Handling Errors using Try Methods
Collecting Errors
Progress Windows, Message, Error, and Confirm Methods

Error handling methods in AL


For examples of using different error handling methods in AL, see the following table:

M ET H O D DESC RIP T IO N

ClearLastError Method Removes the last error message from memory.

Dialog Data Type Represents a dialog window.

Error Method Displays an error message and ends the execution of AL


code.

ErrorInfo Data Type Contains a set of methods that helps identify errors, classify
these errors, send errors to telemetry and display UI
messages. Go to the data type article for an overview.

System Data Type Is a complex data type and contains multiple methods for
getting and classifying errors.

GetLastErrorCallStack Method Gets the call stack from where the last error occurred.

GetLastErrorCode Method Gets the classification of the last error that occurred.

GetLastErrorObject Method Gets the last System.Exception object that occurred.

GetLastErrorText Method Gets the last error that occurred in the debugger.

TIP
If you already know the name of a data type, use the Filter by title field in the upper left corner, above the table of
contents to find the topic faster.

Error handling strategies


For examples of different error handling strategies, see the following table:
IF Y O U WA N T TO. . . T H EN USE

Run a code unit and decide to do something if an error if not Codeunit.run() . For more information, see
occurs. Codeunit.Run return value

Check for an error and show an error dialog to the user. Dialog.Error(Message: ErrorInfo) . For more
information, see Error Method.

Check for an error and show an error dialog to the user with Using the ErrorInfo Data Type with the Error Method
added support information.

Do bulk validations in AL and not show an error dialog for Collecting Errors
each of them to the user.

Catch errors raised by other AL methods Handling Errors using Try Methods

Catch errors/exceptions that are thrown during .NET Handling .NET Exceptions using Try Methods
framework interoperability operations (on-premises only).

Log an error that happens within a database transaction Either log the error in a new session using a background
(that rollback) session, or use Session.LogMessage to log the error to
telemetry.

See also
AL Control Statements
AL Development Environment
AL methods
2/6/2023 • 5 minutes to read • Edit Online

Like other languages, AL methods are a fundamental programming element. A method, also known as a
procedure, is a named group of statements that perform an operation or task. Depending on the scope,
methods can be run, or called, from the same object in which they are declared or from other parts of the
application.
There are two types of methods: system methods (built-in) and user-defined (custom) methods.
Built-in methods are part of the platform. Built-in methods can be used for different purposes, such as
string handling, text formatting, database handling, and so on. For information about the available built-in
methods, see AL method Reference and Essential AL methods. For information about method scope, see
Scope Attribute.
Custom methods are specialized methods for your application to bind the objects, such as tables, pages,
and code units, together to form a unified whole. You can create special methods for use anywhere in the
database.

TIP
If you already know the name of, for example, a data type, method, property, or trigger, use the Filter by title field in the
upper left corner, above the table of contents to find the topic faster. Otherwise, you can scan the table of contents to find
it.

Declaring methods
The method declaration defines the method and has the following syntax:

[Attributes(arguments list)]
local procedure <method_name>(parameter list) <return_value_name> : <data_type>[<length>]

Snippet support
Typing the shortcut tprocedure will create the basic structure for a method when using the AL Language
extension in Visual Studio Code.
Attributes (optional)
An attribute is a modifier on a method declaration that specifies information that controls the method's use and
behavior. Adding an attribute on a method declaration is also known as decorating a method. For example,
decorating a method with the Integration attribute sets the method to be an event publisher. An attribute can
have one or more arguments that set properties for the method instance.
Attributes are placed before the method. For information about the available attributes, see Method Attributes.
Local and global scope
A method can be a local method or global method. A local method can only be accessed or called from inside
the object in which it is declared. A global method can be called from inside the object in which it is declared and
from other objects.
To declare a local method, start the declaration with local :
local procedure Mymethod();

To declare a global method, omit local :

procedure Mymethod();

Parameters (optional)
A parameter is one or more variables or expressions that are sent to the method through the method call. The
parameter provides information to the method, and the method can modify that information. In the method
declaration, you place the parameters in parentheses () . If there is more than one parameter, the parameters
are separated by semicolons. A parameter is defined by a data type. Some data types, such as Record , require
an additional subtype.
For example, the following method declaration includes two parameters: MyCustomer and MyDimension :

procedure MyMethod(MyCustomer : Record Customer; var MyDimension : ARRAY [2] OF Boolean)

This example also illustrates how parameters can be passed by value or passed by reference. The MyCustomer
parameter is passed by value, and the MyDimension parameter is passed by reference in the example above. For
more information, see the section Parameters below.
Return values (optional)
A method can return data that can be then coded against. A return value is defined by a name (optional), data
type, and optional length depending on the data type.
For example, if the return value is a Text DataType, the text might have a length of 50.

procedure MyMethod() ReturnValue: Text[50]


var result : Text[50];
begin
// do something important where result is calculated
ReturnValue := result;
end;

Calling methods
You can run, or call, a built-in or a custom method by using its name in a method call statement. When a method
is called the current application sequence is suspended and the code on the method is run. When the method
code is completed, the application code sequence returns to where the method was called from. How the
method is called determines what happens when it returns.
A method can be used as part of an expression. For example, the following code uses a method named
CalculatePrice as an expression:

TotalCost := Quantity * CalculatePrice;

In this case, the CalculatePrice method must return a value that is used in evaluating the expression. This
return value is then multiplied by the Quantity variable and that result is assigned to the TotalCost variable.
A method can also be run by using a method call statement. This statement only calls the method and does not
return any value. The following is an example of calling a method named MyRunMethod :
if Quantity > 5 then
MyRunMethod;

The MyRunMethod returns no data back to the calling code.


Parameters
In a method call, the parameters are separated by commas, and the optional parameters may be omitted
starting from the right. For example, this means that if a method has three optional parameters, then you cannot
omit the second parameter without omitting the third parameter.
When passing parameters there are two options; passing by value, which is the default behavior, or passing by
reference, in which case you must specify the var keyword.
If a parameter is passed by value, then a copy of the variable is passed to the method. Any changes that
the method makes to the value of the variable are local changes that affect only the copy, not the variable
itself.
If a parameter is passed by reference, then a reference to the variable is passed to the method. The
method can change the value of the variable itself.

Example 1
The following shows the syntax for a method. The first example shows a method with two mandatory
parameters.

method(Parameter1, Parameter2)

Some built-in methods have optional parameters, the syntax is shown below. The optional parameters may be
omitted starting from the right.

method([Optional1] [, Optional2] [, Optional3])

The method that uses the syntax above can be called by using the following code.

method(Optional1, Optional2)

Example 2
ABS is an example of an AL method that has a fixed number of parameters (1).

Value := -1033; //A negative integer value


PositiveValue := ABS(Value); //Calculate the positive value 1033

Example 3
The method DMY2DATE is an example of a method that can be called by using a variable number of parameters.

NewDate := DMY2DATE(5, 11, 1992); //Returns the date November 5, 1992

Depending on the use of the DMY2DATE method, one, two, or three parameters can be passed to the method
because the second and third parameters are optional. When the second and third parameters are not used,
values from the system date are used as default values.

Example 4
You can assign the return value of a method to a variable.

ReturnVal := MyMethod(Param1);

Example 5
In this example, MyMethod returns a Boolean value. You can use the return value in a conditional statement.

if (MyMethod(Param1)) then
<Statement1>
else
<Statement2>

See Also
Development Overview
AL Methods
AL Simple Statements
AL Control Statements
System-Defined Variables
2/6/2023 • 2 minutes to read • Edit Online

Dynamics 365 Business Central automatically declares and initializes several variables that you can use when
you develop applications. The following table describes the system-defined variables.

SY ST EM - DEF IN ED VA RIA B L E DESC RIP T IO N

Rec When a record is modified, this variable specifies the current


record, including the changes that are made.

xRec When a record is modified, this variable specifies the original


values of the record before the changes.

CurrPage This variable specifies the current page.

CurrReport This variable specifies the current report.

RequestOptionsPage This variable specifies the request options page for the
current report.

CurrFieldNo This variable specifies the field number of the current field in
the current table. Retained for compatibility reasons.

Using Rec and xRec


The following example shows how to use the Rec and xRec pair of records.
In an application, data is stored in two tables, a header table and a line table. The header table contains general
information about, for example, sales orders, while the line table contains the specific order lines. The page that
you use to enter information into the header table has fields that contain the customer’s address. These fields
are related to the Customer table, and can be filled by using a lookup method in the field that establishes the
relationship. In the header table, only the customer number is stored, and the other fields that have customer
information, such as name and address, are retrieved from the Customer table when the Customer No. field
is validated.
In some situations, the user should be able to change the customer number, and in other situations the user
shouldn't be able to change it. For example, if the order has already been shipped, the user shouldn't be able to
change the customer number. If there's an incorrect number on an order that hasn't been processed completely,
the user should be able to correct the error.
You could use the Rec and xRec variables to design your application in the following way:
When validating the customer number field, check whether the order has shipped.
If the order has shipped, compare the customer number fields in the Rec and xRec records. If they differ, reject
the change.

Using CurrPage
You can access the controls of the page through the CurrPage variable and set the dynamic properties of the
page and its controls. The CurrPage.Editable variable reflects the runtime value of the Editable property, which
can be changed at design-time, programmatically, or by the user when switching view modes on a page. The
CurrPage.Update([SaveRecord]) variable can be used to save the current record and then update the controls on
the page. When the View mode on a page is false , then the Edit, New, and Delete modes are true .

Using CurrReport
You can access properties of a report through the CurrReport variable and set them dynamically. For example,
by using CurrReport.Preview, you can determine if the report is being run in preview mode.

Using RequestOptionsPage
You can access properties of the request page through the RequestOptionsPage variable and set them
dynamically.

See Also
AL Method Reference
Properties
Preprocessor Directives in AL
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

In AL, like in other programming languages, preprocessor directives can be used to make code conditional, to
suppress warnings, or to enable the ability to expand and collapse in code. Preprocessor directives can be
divided into the following groups. For more information about each type, use the links provided in the following
section.
Conditional directives
Regions
Pragmas
Any code can be made conditional, including table fields, and checked using a conditional directive. To check
code using a conditional directive, you must define a symbol to check. A symbol returns a boolean value; true
or false . Symbols can be defined at the beginning of a source file and the scope of the specific symbol is the
file that it's defined within. You can also define symbols in the app.json file, and then the scope is global for the
extension.

NOTE
Built-in symbols are currently not supported in AL. Symbols must be defined in a specific file or in the app.json file.

NOTE
User personalization and profile configuration (including profile copy) are not meant to work with directives, which means
that they are ignored by the platform in the cases of #pragma, #region, #endregion and fail with an error when they are
not supported for #if, #elif, #define, etc.

Conditional directives
The following conditional preprocessor directives are supported in AL.

C O N DIT IO N A L P REP RO C ESSO R DIREC T IVE DESC RIP T IO N

#if Specifies the beginning of a conditional clause. The #endif


clause ends it. Compiles the code between the directives if
the specified symbol being checked is defined.

#else Specifies a compound conditional clause. If none of the


preceding clauses evaluate to true , the compiler will
evaluate code between #else and #endif .

#elif Combines else and if . If #elif is true the compiler


evaluates all code between #elif and the next conditional
directive.
C O N DIT IO N A L P REP RO C ESSO R DIREC T IVE DESC RIP T IO N

#endif Specifies the end of a conditional clause that begins with


#if .

#define Defines a symbol that can be used to specify conditions for a


compilation. For example, #define DEBUG . The scope of the
symbol is the file that it was defined in.

#undef Undefines a symbol.

Defining preprocessorSymbols
Symbols can be defined globally in the app.json file. A symbol can also be defined using the #define directive
in code, but if symbols are defined in the app.json file, they can be used globally. The following example defines
DEBUG as a global symbol. This can then be used from code as illustrated in the following Conditional code
example. A symbol has a boolean value that means it evaluates to true or false .
The app.json syntax is:

"preprocessorSymbols": [name [,name2]]

For example:

"preprocessorSymbols": [ "DEBUG","PROD"]

For more information, see JSON Files.

Example
#if DEBUG
trigger OnOpenPage()
begin
Message('Only in debug versions');
end;
#endif

See Also
Development in AL
AL Development Environment
Conditional directives
Region Directive in AL
Pragma Directive in AL
Deprecating Explicit and Implicit With Statements
Best Practices for Deprecation of Code in the Base App
ObsoleteState Property
ObsoleteReason Property
ObsoleteTag Property
Obsolete Attribute
Region Directive in AL
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

Region
The #region directive is used to mark a block of code that you can expand or collapse. This can, for example, be
useful for larger files for better readability or for focusing on code that you're currently working on. The
#endregion specifies the end of a #region block of code.

NOTE
On the first line of the #region a text comment can be added to describe the purpose of the block of code, see the
following example.

Syntax
#region [comment]
code

#endregion

Remarks
A #region block must be terminated with a #endregion directive.
A #region block can't overlap with an #if block. However, a #region block can be nested in an #if block,
and an #if block can be nested in a #region block.

Example
In this example, the #region directive makes a code block that is up for refactoring collapsible.

#region Ugly code - let's not look at this


procedure UglyCode()
begin
// No one should look at this
end;
#endregion

See Also
Development in AL
AL Development Environment
Pragma Directive in AL
Conditional directives
Deprecating Explicit and Implicit With Statements
Pragma Directive in AL
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

Pragma
The #pragma directive gives the compiler special instructions for the compilation of the file in which it appears.
The #pragma directive has many actions that can be used with the pragma instructions in the following sections,
which are disable , restore , and enable .
AL supports the following pragma instructions:
Pragma ImplicitWith
Pragma Warning

See Also
Development in AL
AL Development Environment
Region Directive in AL
Conditional directives
Deprecating Explicit and Implicit With Statements
Using Access Modifiers in AL
2/6/2023 • 2 minutes to read • Edit Online

Access modifiers are used to set accessibility of tables, table fields, codeunits, and queries, which controls
whether the object can be used from other code in your module or other modules. Access modifiers in AL are
designed to create solid APIs, by limiting the symbols that dependant modules can take a reference on. Limiting
the API surface can hide implementation details and allow for later refactoring of code without breaking external
code.
You set the object accessibility by using the Access Property. If the Access property isn't specified; default is
Public .

NOTE
In AL, access modifiers are primarily intended for designing APIs and cannot be used as a security boundary.

Access modifiers
The access modifiers that are available in AL are:

A C C ESS M O DIF IER DESC RIP T IO N

internal The object or field can be accessed only by code in the same
module, but not from another module.
Note: This accessibility level is controlled by the
internalsVisibleTo setting. For more information, see
JSON Files

local The field can be accessed only by code in the same table or
table extension where the field is defined.
Note: Applies to table fields only.

protected The field can be accessed only by code in the same table or
table extensions of that table.
Note: Applies to table fields only.

public The object or field can be accessed by any other code in the
same module and in other modules that references it.
Note: This is the default value.

Setting access to internal is linked to the JSON Files setting internalsVisibleTo .

IMPORTANT
Access modifiers are only taken into consideration at compile time. For example, at compile time, a table with
Access = Internal can't be used from other modules that don't have access to the internals of the module where the
table is defined, but at runtime, any module can access the table by using reflection-based mechanisms such as
RecordRef , or TransferFields . And the OnRun trigger can be run on internal codeunits by using Codeunit.Run .
Setting the object accessibility level as Access = Internal; cannot be used as a security boundary. Also see JSON Files.
See Also
AL Development Environment
Access Property
XML Comments in Code
2/6/2023 • 4 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

In Dynamics 365 Business Central, you can add documentation directly in your source code by including XML
elements in special comment fields before the block of code that the comment refers to. The documentation
comment must immediately precede a user-defined type that it annotates, for example a codeunit, table,
interface, or a member such as a field or method. The syntax for adding XML comments in your code is triple
slashes /// followed by one of the supported XML tags. There's IntelliSense support for writing documentation
comments that also provides a template comment on entering the third slash in the triple slash.
Documentation comments are visible when you hover over source symbols, in completion lists, and in signature
help. By adding XML comments in code, you can improve readability, add useful information about the
implementation, and help others take over code that you wrote. With XML comments, you also enable
IntelliSense in Visual Studio Code on the AL objects that you add in the code as a help to other developers,
working with or extending your code. When your code is documented using XML comments, it means that when
you've built an extension and someone extends this code, they'll get inline documentation when they call the
given object.

NOTE
Integration with documentation generator tools like DocFx and SandCastle is currently not supported.

NOTE
If you have the allowDownloadingSource setting in the app.json file set to false and you then download an app
package; the app package won't contain any XML comments.

Supported XML tags


The following table lists the XML elements that are supported for AL.

TO P - L EVEL XM L TA G DESC RIP T IO N SY N TA X

<summary> A summary of the object <summary>description</summary>

<param> Used in method declarations to <param


describe one or more parameters name="name">description</param>
defined in the method. For each
parameter, specify the name and a
description.

<returns> Used in method declarations to <returns>description</returns>


describe the return value of the
method.

<example> Used to specify an example of how to <example>description</example>


use a given codeunit or object.
TO P - L EVEL XM L TA G DESC RIP T IO N SY N TA X

<remarks> Used to supplement information given <remarks>description</remarks>


in the <summary> section.

F O RM AT T IN G XM L TA G DESC RIP T IO N SY N TA X

<paramref> Specifies a reference to a parameter in <paramref name="name"/>


a <summary> or <remarks> block.

<para> Allows structuring text inside a <para>paragraph</para>


<summary> , <remarks> , or
<returns> tag.

<b> Allows formatting text as bold inside a <b>bold</b>


top-level tag.

<i> Allows formatting text as italic inside a <i>italic</i>


top-level tag.

<c> Specifies that text within a description <c>inline code</c>


should be marked as code inside a
top-level tag.

<code> Specifies that multiline text within a <code>code block</code>


description should be marked as code
inside a top-level tag.

<list> Specifies a list formatted as a bulleted <list


or numbered list, or as a table in a type="bullet|number|table">
<summary> or <remarks> block. . See full List syntax below.

List syntax

<list type="bullet|number|table">
<listheader>
<term>term</term>
<description>description</description>
</listheader>
<item>
<term>term</term>
<description>description</description>
</item>
</list>

Example
The following example is taken from the Email.Codeunit.al file in the System Application. In this example, the
parameter EmailMessageId is documented using the <param> syntax.
/// <summary>
/// Provides functionality to create and send e-mails.
/// </summary>

codeunit 8901 "Email"


{
Access = Public;

/// <summary>
/// Enqueues an email in the outbox to be sent in the background.
/// </summary>
/// <param name="EmailMessageId">The ID of the email to enqueue</param>
procedure Enqueue(EmailMessageId: Guid)
begin
EmailImpl.Enqueue(EmailMessageId);
end;
...

Special symbols
For special symbols, such as angle brackets, to appear in text of a documentation comment, use the HTML
encoding of < and > , which is &lt; and &gt; respectively. The following example illustrates how.

/// <summary>
/// This property always returns a value &lt; 1.
/// </summary>

Writing tips
Code comments improve the readability of the code that you've developed and they're useful for anyone
modifying or maintaining that code. Furthermore, code comments form the basis of auto-generated
documentation. Great code comments must do the following:
1. Never state the obvious.
2. Write a meaningful comment, use precise wording to describe why.
3. Imagine yourself in the shoes of the developer using this piece of code, what would you want to know?
4. For properties and methods, use active wording such as Sets..., Gets..., and Specifies..., and then explain what
it does.
5. List all pre-conditions for your parameters (can't be null, must be within a certain range, and so on).
6. List any post-conditions that could influence how callers deal with return values.
7. List any exceptions the method may throw (and under what circumstances).
8. If similar methods exist, explain the differences between them.
9. Call attention to anything unexpected (such as modifying global state).
10. Enumerate any side-effects, if there are any.
11. Be consistent.
12. Be concise.
13. Make sure that your comments are reviewed.
For more examples, see https://stackoverflow.com/questions/3143324/what-are-best-practices-for-
documenting-c-sharp-code-with-xml-comments.

See also
AL Development Environment
Developing Extensions in AL
Pages Overview
Microsoft Writing Style Guide
The Code Analysis Tool
2/6/2023 • 3 minutes to read • Edit Online

This article shows you how to use static code analysis tool on an AL project from within Visual Studio Code.

Enable the code analysis


Follow the steps below to create a basic project in AL.
1. Press Alt + A, Alt + L to create a new project.
2. Open the Command Palette Ctrl+Shift+P and choose either User Settings or Workspace Settings .
3. Under Extensions , go to Al Language extension configuration . When you scroll down, you'll find Code
Analyzers section, choose Edit in settings.json .
4. Set the al.enableCodeAnalysis in the settings file to true .
"al.enableCodeAnalysis": true
5. In the al.codeanalyzers setting, use Ctrl+Space to pick from the available code analyzers. Separate the list
of code analyzers with commas. For more information about the available analyzers, see AppSourceCop,
CodeCop, PerTenantExtensionCop, and UICop.
At this point, the selected analyzers will run on your project. Next, add some code to the project that will, in the
following example, be used to demonstrate a violation of the AA0001 "There must be exactly one space
character on each side of a binar y operator such as := + - AND OR =." code analysis rule.

NOTE
By default, code analysis is run in the background.

Add your own code to the project


In the Visual Studio Code Explorer, open the HelloWorld.al file and replace the existing code with the following
code:

pageextension 50100 CustomerListExt extends "Customer List"


{
trigger OnOpenPage();
var
result: Integer;
begin
// The following line will trigger the warning
// AA0001 "There must be exactly one space character on each side
// of a binary operator such as := + - AND OR =."
result := 2+2;
Message('2 + 2 = ' + Format(result));
end;
}

View the results of the code analysis


The code analysis tools will run in the background. You'll see the faulty expression underlined and the warning
"There must be exactly one space character on each side of '+'." will be displayed if you move cursor
over the underlined code. You can also view the list of issues by selecting the View tab of Visual Studio Code
and choosing the Problems option.
Using the Ctrl+Shift+B shortcut to build your project will run the code analysis tools on the entire project and
the detected issues will be displayed in the Output window of Visual Studio Code. For more information about
AL keyboard shortcuts, see Keyboard shortcuts.

Code analyzers
A code analyzer is a library that builds on the compiler's functionality to offer enhanced analysis of the syntax
and semantics of your code at build time. The AL Language extension for Visual Studio Code contains four
analyzers:
CodeCop is an analyzer that enforces the official AL Coding Guidelines. For more information about the
CodeCop rules, see CodeCop Analyzer Rules.
PerTenantExtensionCop is an analyzer that enforces rules that must be respected by extensions meant to
be installed for individual tenants. For more information about the PerTenantExtensionCop rules, see
PerTenantExtensionCop Analyzer Rules.
AppSourceCop is an analyzer that enforces rules that must be respected by extensions meant to be
published to Microsoft AppSource. For more information about the AppSourceCop rules, see AppSourceCop
Analyzer Rules.
UICop is an analyzer that enforces rules that must be respected by extensions that are meant to customize
the Web Client. For more information about the UserInterfaceCop rules, see UICop Analyzer Rules.

Enable code analysis on large projects


In order to improve performance while running code analysis on large projects, you can switch off running code
analysis in the background. To do so, open the Command Palette Ctrl+Shift+P and choose either User
Settings or Workspace Settings . Then, specify the setting "al.backgroundCodeAnalysis": false in settings file.

See Also
Using the Code Analysis Tools with the Ruleset
Ruleset for the Code Analysis Tool
Development in AL
Directives in AL
Debugging in AL
AL Language Extension Configuration
Ruleset for the Code Analysis Tool
2/6/2023 • 2 minutes to read • Edit Online

In an AL project, you can use a custom ruleset file to specify how code analysis will report the issues it
encounters. Different settings can affect how rules are applied and each ruleset file name must follow the
pattern <name>.ruleset.json to benefit from IntelliSense in Visual Studio Code.

NOTE
Use the truleset and trule snippets provided by the AL Language extension to create your ruleset.

The following table describes the schema of a ruleset object:

SET T IN G M A N DATO RY TYPE VA L UE

name Yes String The name of the ruleset.

description No String The description of the


ruleset. You can use this
setting to document the
purpose of the ruleset.

generalAction No Error | Warning | Info | Hidd The action to apply to all


en the diagnostics that have
rules defined in this file or in
other files that have a
Default action specified. It
also applies to all the
diagnostics generated by
the current set of analyzers
that don't have a rule
defined. If an included file
has a stricter
generalAction , that one
will be used.

includedRuleSets No Array of IncludedRuleSet List of external ruleset files


to include in the current
ruleset. The order in which
the files are processed is
undefined.

rules No Array of Rule Collection of rules to apply


to diagnostics generated by
analyzers.

An IncludedRuleSet is a complex JSON object that defines the inclusion of an external ruleset file in the
current ruleset, and has the following properties:

SET T IN G M A N DATO RY TYPE VA L UE


SET T IN G M A N DATO RY TYPE VA L UE

path Yes String The path to the included


file. For includes specified in
the file to which the
al.ruleSetPath is set, the
path can be absolute or
relative to the project folder.
For files included from the
root ruleset file, the path is
relative to the file. Adding
an entry to the ruleset path
and saving it, will
automatically be applied to
all the projects that are
using the ruleset.

action Yes Error | Warning | Info | Hidd The action to apply for all
en | None | Default the diagnostics that have
an action specified in the
included ruleset that is
different from None and
Hidden .

A Rule is a complex JSON object that defines how you can process a specific diagnostic. A Rule object has the
following properties:

SET T IN G M A N DATO RY TYPE VA L UE

id Yes String The string that uniquely


identifies a diagnostic.

action Yes Error | Warning | Info | Hidd The action to apply if the
en | None diagnostic is emitted. There
can't be two rules with the
same id and different
actions in the same rule file.

Examples
The following example shows a ruleset that sets the severity of rule AA0001 : There must be exactly one
space character on each side of a binar y operator such as := + - AND OR =. provided by the
CodeCop analyzer to Error .

{
"name": "Company ruleset",
"description": "These rules must be respected by all the AL code written within the company.",
"rules": [
{
"id": "AA0001",
"action": "Error",
"justification": "This diagnostic helps to improve readability. It must be respected in all
cases."
}
]
}

The following example shows a project-specific ruleset that extends a company-wide ruleset contained in the file
company.ruleset.json and sets the severity of the rule AA0005 : Only use BEGIN..END to enclose
compound statements. provided by the CodeCop analyzer to Info .

{
"name": "Personal Project ruleset",
"description": "A list of project specific rules",
"includedRuleSets": [
{
"action": "Default",
"path": "./company.ruleset.json"
}
],
"rules": [
{
"id": "AA0005",
"action": "Info",
"justification": "For this specific project, this diagnostic should be informational."
}
]
}

See Also
Using the Code Analysis Tools
Using the Code Analysis Tools with the ruleset
AL Development Environment
Directives in AL
AL Language Extension Configuration
Using the Code Analysis Tools with the Ruleset
2/6/2023 • 3 minutes to read • Edit Online

This article helps you to customize a ruleset for the severity of diagnostics produced by the code analysis tools
that are part of the AL Language extension for Visual Studio Code.

Use rulesets with code analysis


First, create a basic project in AL by following the steps below:
1. Press Alt + A, Alt + L to create a new project.
2. Open the Command Palette by using the Ctrl+Shift+P shortcut and choose either User Settings or
Workspace Settings .
3. Under Extensions , go to Al Language extension configuration . When you scroll down, you'll find Code
Analyzers section, choose Edit in settings.json .
4. Set the al.enableCodeAnalysis in the settings file to true .
"al.enableCodeAnalysis": true
5. In the al.codeanalyzers setting, use Ctrl+Space to pick from the available code analyzers. Separate the list
of code analyzers with commas. For more information about the available analyzers, see AppSourceCop,
CodeCop, PerTenantExtensionCop, and UICop.
At this point, the selected analyzers will run on your project. Next, add some code to the project that will, in the
following example, be used to demonstrate violations of the AA0001 "There must be exactly one space
character on each side of a binar y operator such as := + - AND OR =." code analysis rule.

Add your own code to the project


In the Visual Studio Code Explorer, open the HelloWorld.al file and replace the existing code with the following
code:

pageextension 50100 CustomerListExt extends "Customer List"


{
trigger OnOpenPage();
var
result: Integer;
begin
// The following line will trigger the warning
// AA0001 "There must be exactly one space character on each side
// of a binary operator such as := + - AND OR =."
result := 2+2;
Message('2 + 2 = ' + Format(result));
end;
}

On the View tab of Visual Studio Code, select the Problems option and you'll see a warning with the message
"There must be exactly one space character on each side of '+'." . In this case, the problem can be fixed
by running the AL Formatter command. For more information, see AL Formatter.

Create and customize a ruleset


To create and customize a ruleset of your own, follow the next steps:
1. On the File tab in Visual Studio Code, choose New File .
2. Save the empty file with a name, for example <name>.ruleset.json and make a note of the file path.
3. Add the following code to the <name>.ruleset.json file:

{
"name": "My Custom ruleset",
"rules": [
{
"id": "AA0001",
"action": "None"
}
]
}

4. In your project settings, set Rule Set Path to the path of the <name>.ruleset.json file, relative to the
project root. For more information about custom rules, see Ruleset for the Code Analysis Tool.

NOTE
Use the truleset and trule snippets provided by the AL Language extension to create your ruleset. The ruleset will
be applied to all the analyzers enabled for the current project. For more information about selectively enabling analyzers,
see The Code Analysis Tools.

Running the code analysis


The code analysis will run in the background and you'll see the warning "There must be exactly one space
character on each side of '+'." disappear from the Problems option in Visual Studio Code.
To trigger a new compilation manually, use the Ctrl+Shift+B shortcut to build your project. For more
information about AL keyboard shortcuts, see Keyboard shortcuts.

Limitations
Changing the contents of the ruleset file won't be detected by the AL Language extension. To see the effects of
changing the ruleset file, you can try any of the following steps:
Reload the window.
In the project settings, change the Rule Set Path setting to an invalid path and save it. Then change it back
and save again.

See also
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools
Directives in AL
Development in AL
Debugging in AL
AL Language Extension Configuration
AppSourceCop Analyzer Rules
2/6/2023 • 10 minutes to read • Edit Online

AppSourceCop is an analyzer that enforces rules that must be respected by extensions meant to be published to
Microsoft AppSource.

Rules
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0001 Tables and table extensions Upgrade Error


that have been published
must not be deleted.

AS0002 Fields must not be deleted. Upgrade Error

AS0003 The previous version of the Upgrade Error


extension could not be
found.

AS0004 Fields must not change Upgrade Error


type, since dependent
extensions may break

AS0005 Fields must not change Upgrade Error


name

AS0006 Tables that have been Upgrade Error


published must not change
name.

AS0009 Key fields must not be Upgrade Error


changed

AS0010 Keys must not be deleted Upgrade Error

AS0011 An affix is required Extensibility Error

AS0013 The field identifier must be Extensibility Error


within the allowed range

AS0014 The project manifest must Extensibility Error


contain the allocated
identifier range

AS0015 TranslationFile must be Extensibility Error


enabled.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0016 Fields of field class 'Normal' Extensibility Error


must use the
DataClassification property
and its value should be
different from ToBeClassified

AS0018 A procedure belonging to Upgrade Error


the public API cannot be
removed

AS0019 Event attributes cannot be Upgrade Error


removed

AS0020 The type of events cannot Upgrade Error


be changed.

AS0021 An argument in an event Upgrade Error


attribute cannot be
changed to false.

AS0022 An external scope cannot Upgrade Error


be removed

AS0023 A return type cannot be Upgrade Error


modified in external
procedures

AS0024 Parameters cannot be Upgrade Error


removed or added in
external procedures

AS0025 Parameters cannot be Upgrade Error


modified, renamed, or
removed from events.

AS0026 The type and subtype of Upgrade Error


parameters cannot be
modified in events and
external procedures

AS0027 Modifying the array size of Upgrade Error


a parameter in events and
external procedures is not
allowed

AS0028 Reducing the array size of a Upgrade Error


parameter in events and
external procedures is not
allowed

AS0029 Pages and PageExtensions Upgrade Error


that have been published
must not be deleted, since
dependent extensions may
break
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0030 Pages that have been Upgrade Error


published must not be
renamed.

AS0031 Actions that have been Upgrade Error


published must not be
deleted.

AS0032 Controls that have been Upgrade Error


published must not be
deleted.

AS0033 Views that have been Upgrade Error


published must not be
deleted.

AS0034 Unsupported table Upgrade Error


property change

AS0036 Unsupported table field Upgrade Error


property change

AS0038 Unsupported table key Upgrade Error


property change

AS0039 Removing properties that Upgrade Error


cause destructive changes is
not allowed

AS0041 Table field property changes Upgrade Error


that cause destructive
changes must not be
removed

AS0042 Table key property changes Upgrade Error


that cause destructive
changes must not be
removed

AS0043 The clustered key must not Upgrade Error


be deleted

AS0044 Property changes that Upgrade Error


cause destructive changes
are not allowed

AS0047 The extension name is too Extensibility Error


long.

AS0048 The publisher name is too Extensibility Error


long.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0049 The access modifier of an Extensibility Error


application object cannot be
changed to a value that
provides less access.

AS0050 The extensibility of an Extensibility Error


application object cannot be
removed

AS0051 Manifest property is Extensibility Error


required for AppSource
submission

AS0052 The property 'url' must be Extensibility Error


set to a valid URL

AS0053 The compilation target of Extensibility Error


an application must be a
value that is allowed in a
multi-tenant SaaS
environment

AS0054 The AppSourceCop Configuration Error


configuration must specify
the set of affixes used by
the application

AS0055 The AppSourceCop Configuration Hidden


configuration must specify
the list of countries/regions
targeted by the application

AS0056 The country/region codes Configuration Warning


specified in the
'supportedCountries'
property must be valid ISO
3166-1 alpha-2 codes

AS0057 Translations must be Extensibility Hidden


provided for all the locales
in which the application will
be available

AS0058 Only use AssertError in Test Extensibility Error


Codeunits

AS0059 Reserved database tables Extensibility Error


are read-only in a multi-
tenant environment

AS0060 Unsafe methods cannot be Extensibility Error


invoked in an AppSource
application
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0061 Procedures must not Extensibility Error


subscribe to CompanyOpen
events

AS0062 Page controls and actions Extensibility Error


must use the
ApplicationArea property

AS0063 Removing a var modifier in Upgrade Error


events is not allowed

AS0064 Interface implementations Upgrade Error


that have been published
must not be deleted.

AS0065 Interfaces that have been Upgrade Error


published must not be
deleted.

AS0066 A new method to an Upgrade Error


interface that has been
published must not be
added.

AS0067 Adding an interface to an Upgrade Error


enum that has been
published must have a
default implementation.

AS0068 Changing a table Upgrade Error


extension's target is not
allowed.

AS0069 An enum field replacing an Upgrade Error


option field should have at
least the same number of
members.

AS0070 An enum field replacing an Upgrade Error


option field should preserve
the member names.

AS0071 An enum field replacing an Upgrade Error


option field should preserve
the member ordinal values.

AS0072 The ObsoleteTag property Design Hidden


and the Tag in the Obsolete
attribute must be set to the
next release version.

AS0073 Obsolete Tag must be set. Design Hidden

AS0074 The Obsolete Tag must be Design Hidden


the same across branches.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0075 Obsolete Reason must be Design Warning


set.

AS0076 Obsolete Tag format. Design Hidden

AS0077 Adding a var modifier in Upgrade Error


events is not allowed

AS0078 Adding or removing a var Upgrade Error


modifier in external
procedures is not allowed

AS0079 An affix is required for Extensibility Warning


procedures defined in
extension objects.

AS0080 Fields must not decrease in Upgrade Error


length

AS0081 InternalsVisibleTo should Extensibility Warning


not be used as a security
feature.

AS0082 It is not allowed to rename Upgrade Error


an enum value.

AS0083 It is not allowed to delete a Upgrade Error


value from an enum.

AS0084 The ID range assigned to Extensibility Error


the extension must be
within the allowed range

AS0085 The 'application' property Extensibility Warning


should be used instead of
explicit dependencies

AS0086 Fields must not increase in Upgrade Warning


length

AS0087 Translations of enum value Extensibility Warning


captions must not contain
commas

AS0088 Objects with an ID that can Upgrade Error


be referenced and which
have been published must
not be deleted.

AS0089 Objects that can be Upgrade Error


referenced and which have
been published must not be
deleted.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0090 Objects that can be Upgrade Error


referenced and which have
been published must not be
renamed.

AS0091 One or more dependencies Upgrade Error


of the previous version of
the extension could not be
found.

AS0092 The app.json file must Configuration Warning


specify an Azure Application
Insights resource.

AS0094 Permission Sets should not Configuration Warning


be defined in XML files.

AS0095 The access modifier of a Configuration Error


table field cannot be
changed to a value that
provides less access.

AS0096 The name of an extension Configuration Error


cannot be changed.

AS0097 The publisher name of an Configuration Error


extension cannot be
changed.

AS0098 An affix is needed. Extensibility Warning

AS0099 The member ID should be Extensibility Info


within the allowed range

AS0100 The 'application' property in Extensibility Error


the app.json file must be
specified.

AS0101 The 'Isolated' argument Upgrade Error


cannot be changed, added,
or removed.

AS0102 Cannot add a return value Upgrade Error


to a procedure

AS0103 Table definitions must have Configuration Warning


a matching permission set.

AS0104 The extension name is not Extensibility Error


valid.

AS0105 Object pending obsoletion Design Error


contains an expired
ObsoleteTag.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AS0106 A variable belonging to the Design Error


public API cannot be
removed.

AS0107 The access modifier of a Design Error


variable that belongs to the
public API cannot be
changed to a value that
provides less access.

AS0108 The type of a variable Design Error


belonging to the public API
cannot be changed.

AS0109 The type of the table has Upgrade Warning


changed from Normal to
Temporary.

NOTE
Several rules enforced by the AppSourceCop analyzer are incompatible with rules enforced by the PerTenantExtensionCop.
Make sure to enable only one of these at a time.

NOTE
Failing to comply with the rules whose default severity is set to Error will fail the submission of your extension to the
AppSource marketplace. It is recommended, but not mandatory to comply with the rules whose severity is marked as
Warning or Info .

Configuration
The AppSourceCop analyzer can be further configured by adding a file named AppSourceCop.json in the
project's root folder. The AL Language extension will offer IntelliSense for this file.
The following table describes the settings in the AppSourceCop.json file:

SET T IN G M A N DATO RY VA L UE

name No The name of a previous version of this


package with which you want to
compare the current package for
breaking changes.

publisher No The publisher of a previous version of


this package with which you want to
compare the current package for
breaking changes.

version Yes The version of a previous version of


this package with which you want to
compare the current package for
breaking changes.
SET T IN G M A N DATO RY VA L UE

mandatoryAffixes No Affixes that must be prepended or


appended to the name of all new
application objects, extension objects,
and fields.

supportedCountries No The set of country codes, in the alpha-


2 ISO 3166 format, in which the
application will be available.

targetVersion No Specifies the next Major.Minor version


of the extension in the current branch
in order to validate the ObsoleteTag
values with AS0072. This is only
relevant when the default
obsoleteTagPattern '(\d+)\.(\d+)' is
used. This property is being
deprecated in favor of
obsoleteTagVersion.

obsoleteTagVersion No Specifies the next Major.Minor version


of the extension in the current branch
in order to validate the ObsoleteTag
values with AS0072. This is only
relevant when the default
obsoleteTagPattern '(\d+)\.(\d+)' is
used.

obsoleteTagPattern No The Obsolete tag pattern used by


AS0076. This should be a valid regular
expression. By default, the pattern
'(\d+)\.(\d+)' is used.

obsoleteTagPatternDescription No A human-readable description for the


ObsoleteTagPattern regular expression.
This is used in diagnostics reported by
AS0076. By default, 'Major.Minor' is
used.

obsoleteTagAllowedVersions No A comma-separated list of Major.Minor


versions that will be allowed as
ObsoleteTag values by AS0072. This is
only relevant when the default
obsoleteTagPattern '(\d+)\.(\d+)' is
used.

baselinePackageCachePath No The path to the folder containing the


baseline and its dependencies with
which you want to compare the
current package for breaking changes.
By default, the package cache path for
the current project is used (see
'al.packageCachePath' setting).
SET T IN G M A N DATO RY VA L UE

obsoleteTagMinAllowedMajorMinor No The minimum version of ObsoleteTag


(Major.Minor) allowed during
compilation. Referencing an obsolete
pending object with an obsolete tag
lower than the specified version will
trigger the rule AS0105. Note that
enabling this setting has a
performance impact.

The name , publisher , version properties are used for specifying a previous version of the current package.
This package must be located in the baseline package cache folder of your extension. This cache can be specified
using the baselinePackageCachePath property. If this property is not specified, the dependency package cache
path of the extension will be used instead. The al.packageCachePath setting allows you to specify the path to the
folder that will act as the cache for the dependencies symbol files used by your project. AppSourceCop will
compare the previous version of your extension with its current version and will report any breaking changes
introduced by the current package.
The mandatoryAffixes property specifies strings that must be prepended or appended to the names of all new
objects, extension objects and fields. By using these affixes, you can prevent clashes between objects added by
your extension and objects added by other extensions.
The supportedCountries property specifies the codes that correspond to the countries for which the product
allows AppSource submissions. For more information, see Availability and supported Countries/Regions and
Translations
The properties obsoleteTagVersion , obsoleteTagPattern , and obsoleteTagPatternDescription can be used to
enable additional validation on object obsoletion. These are not required for AppSource submissions.

Example
In the following example, we will configure AppSourceCop to validate that all new elements have a name that
contains one of the specified affixes.

NOTE
Make sure that code analysis is enabled and ${AppSourceCop} is specified in the list of enabled code analyzers. For more
information see AL Language Extension Configuration.

We start by creating the default "Hello world" extension.

pageextension 50100 CustomerListExt extends "Customer List"


{
trigger OnOpenPage();
begin
begin
Message('App published: Hello world');
end;
end;
}

We continue by adding the configuration file AppSourceCop.json in the project's root folder and setting its
content to the following.
{
"mandatoryAffixes": [ "Foo", "Bar" ]
}

IMPORTANT
If you are running a multi-root workspace environment, you must have one AppSourceCop.json file in the root folder of
each of the projects. For more information, see Working with multiple AL project folders within one workspace.

You are immediately greeted by the following error message:

AS0011: The identifier 'CustomerListExt' must have at least one of the mandatory affixes 'Foo, Bar'.

Prepending Foo to the name of the page extension object will fix this error and prevent clashes between this
page extension and page extensions added by other developers.

NOTE
It is still possible to use the mandatoryPrefix and mandatorySuffix properties in the AppSourceCop.json . For more
information see AS0011.

See Also
Using the Code Analysis Tool
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools with the Ruleset
CodeCop Analyzer Rules
2/6/2023 • 5 minutes to read • Edit Online

CodeCop is an analyzer that enforces the official AL Coding Guidelines.

Rules
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0001 There must be exactly one Readability Warning


space character on each
side of a binary operator
such as := + - AND OR =.

AA0002 There must be no space Readability Warning


character.

AA0003 There must be exactly one Readability Warning


space character between
the NOT operator and its
argument.

AA0005 Only use BEGIN..END to Readability Warning


enclose compound
statements.

AA0008 Function calls should have Readability Warning


parenthesis even if they do
not have any parameters.

AA0013 When BEGIN follows THEN, Readability Warning


ELSE, DO, it should be on
the same line, preceded by
one space character.

AA0018 The END, IF, REPEAT, UNTIL, Readability Warning


FOR, WHILE, and CASE
statement should always
start a line.

AA0021 Variable declarations should Readability Warning


be ordered by type.

AA0022 Substitute the IF THEN ELSE Readability Warning


structure with a CASE.

AA0040 Avoid using nested WITH Readability Warning


statements.

AA0072 The name of variables and Readability Info


parameters must be
suffixed with the type or
object name.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0073 The name of temporary Readability Warning


variable must be prefixed
with Temp.

AA0074 TextConst and Label Readability Warning


variable names should have
an approved suffix.

AA0087 Lowering permissions Design Warning


should only be used in tests

AA0100 Do not have identifiers with Design Warning


quotes in the name.

AA0101 Use camel case property Design Warning


values in pages of type API.

AA0102 Use camel case name for Design Warning


field controls in pages of
type API.

AA0103 Use camel case property Design Warning


values in queries of type
API.

AA0104 Use camel case name for Design Warning


column controls in queries
of type API.

AA0105 PagePart controls must not Design Error


refer to parent pages.

AA0106 A page of type API can only Design Error


refer to the same subpage
once.

AA0131 String parameters must Design Warning


match placeholders.

AA0136 Do not write code that will Design Warning


never be hit.

AA0137 Do not declare variables Design Warning


that are unused.

AA0139 Do not assign a text to a Design Warning


target with smaller size.

AA0150 Do not declare parameters Design Warning


by reference if their values
are never changed.

AA0161 Only use AssertError in Test Design Warning


Codeunits.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0175 Only find record if you need Design Warning


to use it.

AA0181 The FindSet() or Find() Design Warning


methods must be used only
in connection with the
Next() method.

AA0189 Only use a correct values of Design Warning


ApplicationArea.

AA0194 Only write actions that have Design Warning


an effect.

AA0198 Do not use identical names Design Warning


for local and global
variables.

AA0199 Use only a correct order for Design Warning


ApplicationArea.

AA0200 When ApplicationArea is set Design Warning


to 'All', no other values for
ApplicationArea should be
specified.

AA0201 When ApplicationArea is set Design Warning


to 'Basic', you must also
specify 'Suite'.

AA0462 The CalcDate should only Localizability Warning


be used with DataFormula
variables. Alternatively the
string should be enclosed
using the <> symbols.

AA0202 To avoid confusion, do not Design Warning


give local variables the
same name as fields,
methods, or actions in the
same scope.

AA0203 To avoid confusion, do not Design Warning


give methods the same
name as fields or actions in
the same scope.

AA0204 To avoid confusion, do not Design Warning


give global variables the
same name as fields,
methods, or actions in the
same scope.

AA0205 Variables must be initialized Design Warning


before usage.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0206 The value assigned to a Design Warning


variable must be used.

AA0207 The EventSubscriber Design Warning


method must be local.

AA0210 Avoid non-indexed fields Design Info


into filtering.

AA0211 Avoids a runtime error from Design Warning


using CalcFields on a field
that is not a FlowField or a
field of type Blob.

AA0213 Obsoleted object must have Design Warning


a state 'Pending' or
'Removed' and a
justification specifying why
this field is being obsoleted.

AA0214 The local record should be Design Warning


modified before saving to
the database.

AA0215 Follow the style guide Readability Warning


about the best practices for
naming.

AA0216 Use a text constant for Localizability Warning


passing user messages and
errors without
concatenations.

AA0217 Use a text constant or label Localizability Warning


for format string in
StrSubstNo.

AA0218 You must write a tooltip in Localizability Warning


the Tooltip property for all
controls of type Action and
Field that exist on page
objects.

AA0219 The Tooltip property of Localizability Warning


Fields must start with
'Specifies'.

AA0220 The value of the Tooltip Localizability Warning


property of Fields must be
filled.

AA0221 You must specify a Localizability Warning


OptionCaption property for
all fields which source
expressions is not a table
field.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0222 SIFT index should not be Design Warning


used on primary or unique
key.

AA0223 The value of the Localizability Warning


OptionCaption property of
Fields must be filled in.

AA0224 The count of option Localizability Warning


captions specified in the
OptionCaption property is
wrong.

AA0225 You must specify a caption Localizability Warning


in the Caption property for
Fields that exist on page
objects.

AA0226 The value of the Caption Localizability Warning


property of Fields must be
filled in.

AA0227 Optional return value Design Warning


should not be omitted in
upgrade codeunits.

AA0228 The local method must be Design Warning


used; otherwise removed.

AA0230 Version should not be Design Warning


specified for internal
assemblies.

AA0231 StrSubstNo or string Design Warning


concatenation must not be
used as a parameter in the
Error method.

AA0232 The FlowField of a table Design Info


should be indexed.

AA0233 Use Get(), FindFirst() and Design Warning


FindLast() without Next()
method.

AA0235 When using Design Info


'OnInstallAppPerCompany'
you should also add
'Company-
Initialize'::'OnCompanyInitial
ize' event subscriber.

AA0237 The name of non- Readability Warning


temporary variables must
not be prefixed with Temp.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AA0240 Email and Phone No must Design Warning


not be present in any part
of the source code.

AA0241 Use all lowercase letters for Readability Hidden


reserved language
keywords.

AA0242 Limit JIT loads by selecting Design Warning


all fields for load.

AA0243 Running an upgrade Design Warning


codeunit is not allowed.

AA0244 Do not use identical names Design Warning


for parameters and global
variables.

AA0245 To avoid confusion, do not Design Warning


give parameters the same
name as fields, methods, or
actions in the same scope.

AA0448 You must use the Localizability Warning


FieldCaption method
instead of the FieldName
method and TableCaption
method instead of
TableName method.

AA0470 Placeholders should have a Localizability Warning


comment explaining their
content.

See Also
Using the Code Analysis Tool
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools with the Ruleset
PerTenantExtensionCop Analyzer Rules
2/6/2023 • 2 minutes to read • Edit Online

PerTenantExtensionCop is an analyzer that enforces rules that must be respected by extensions meant to be
installed for individual tenants.

Rules
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

PTE0001 Object ID must be in free Extensibility Error


range.

PTE0002 Field ID must be in free Extensibility Error


range.

PTE0003 Procedures must not Extensibility Error


subscribe to CompanyOpen
events

PTE0004 Table definitions must have Configuration Error


a matching permission set.

PTE0005 The compilation target of Extensibility Error


an application must be a
value that is allowed in a
multi-tenant SaaS
environment

PTE0006 Encryption key functions Extensibility Error


must not be invoked.

PTE0007 Test assertion functions are Extensibility Error


not allowed in a non-test
context.

PTE0008 Page controls and actions Extensibility Error


must use the
ApplicationArea property

PTE0009 This app.json property must Extensibility Error


not be used for per-tenant
extensions.

PTE0010 The extension name is too Extensibility Error


long.

PTE0011 The publisher name is too Extensibility Error


long.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

PTE0012 InternalsVisibleTo should Extensibility Warning


not be used as a security
feature.

PTE0013 Entitlements cannot be Configuration Error


defined in an extension.

PTE0014 Permission Sets should not Configuration Warning


be defined in XML files.

PTE0015 The extension name is not Extensibility Error


valid.

See Also
Using the Code Analysis Tool
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools with the Ruleset
UICop Analyzer Rules
2/6/2023 • 2 minutes to read • Edit Online

UICop is an analyzer that enforces rules that must be respected by extensions meant to customize the Web
Client.

Rules
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AW0001 The Web client does not WebClient Warning


support displaying the
Request page of XMLPorts.

AW0002 The Web client does not WebClient Warning


support displaying both
Actions and Fields in Cue
Groups. Only Fields will be
displayed.

AW0003 The Web client does not WebClient Warning


support displaying Repeater
controls containing Parts.

AW0004 A Blob cannot be used as a WebClient Warning


source expression for a
page field.

AW0005 Actions should use the WebClient Info


Image property.

AW0006 Pages and reports should WebClient Info


use the UsageCategory and
ApplicationArea properties
to be searchable.

AW0007 The Web client does not WebClient Error


support displaying Repeater
controls that contain
FlowFilter fields.

AW0008 The Web client only WebClient Warning


supports displaying
Repeater controls in pages
of type List, ListPart, and
Worksheet.

AW0009 Using a Blob with subtype WebClient Warning


Bitmap on a page field is
deprecated. Instead use the
Media/MediaSet data types.
ID T IT L E C AT EGO RY DEFA ULT SEVERIT Y

AW0010 A Repeater control used on WebClient Warning


a List page must be defined
at the beginning of the
area(Content) section.

AW0011 Add PromotedOnly="true" WebClient Info


to some or all promoted
actions to avoid identical
actions from appearing in
both the promoted and
default sections of the
command bar.

AW0012 The Web client does not WebClient Warning


support properties for
teaching tips in certain
contexts.

AW0013 Groups containing WebClient Warning


promoted actions should
not be hidden.

AW0014 Groups containing WebClient Warning


ActionRef targets should
not be hidden.

AW0015 Actions with scope repeater WebClient Warning


must be promoted.

See Also
Using the Code Analysis Tool
Ruleset for the Code Analysis Tool
Using the Code Analysis Tools with the Ruleset
Isolated Storage
2/6/2023 • 2 minutes to read • Edit Online

Isolated Storage is a data storage that provides isolation between extensions, so that you can keep keys/values
in one extension from being accessed from other extensions. Keys/values in the Isolated Storage are accessible
through an API. The option type used for classifying data is DataScope Option Type and the data type used is the
IsolatedStorage Data Type.
The methods supported for IsolatedStorage are:

M ET H O D DESC RIP T IO N F O R M O RE IN F O RM AT IO N , SEE

Set(String, String, [DataScope]) Sets the value associated with the Set(String, String, [DataScope]) Method
specified key within the extension.

Get(String, [DataScope], var Text) Gets the value associated with the Get(String, [DataScope], var Text)
specified key within the extension. Method

Contains(String, [DataScope]) Determines whether the storage Contains(String, [DataScope]) Method


contains a value with the specified key
within the extension.

Delete(String, [DataScope]) Deletes the value with the specified IsolatedStorage.Delete Method
key from the isolated storage within
the extension.

SetEncrypted(String, String, Encrypts and sets the value associated SetEncrypted(String, String,
[DataScope]) with the specified key. The input string [DataScope]) Method
cannot exceed a length of 215 plain
characters; be aware that special
characters take up more space.

See Also
DataScope Option Type
IsolatedStorage Data Type
File Handling and Text Encoding
2/6/2023 • 4 minutes to read • Edit Online

There are several AL methods that you can use to open files, import and export files to and from Dynamics 365
Business Central, and more. For a list of methods, see File Data Type.
The following are recommended best practices for working with files:
Use fully qualified paths to eliminate ambiguity.
Be aware of operating system file access restrictions when designing applications that use files. Consider
which users have access to files and directories and what Access Control List (ACL) that you need to apply
to file directories.

Text encoding
Text encoding is the process of transforming bytes of data into readable characters for users of a system or
program. When you import a file as text or as a stream, the text encoding format ensures that all the language-
specific characters are represented correctly in Dynamics 365 Business Central. When you export a file as text or
as a stream, the text encoding format ensures that all the language-specific characters are represented correctly
in the system or program that will read the exported file.

Encoding formats
You can specify text encoding for the following objects.

O B JEC T O R DATA T Y P E F O R M O RE IN F O RM AT IO N , GO TO

XMLpor ts TextEncoding Property (XMLports)

File OPEN Method (File)

BLOB CREATEINSTREAM Method (BLOB)

CREATEOUTSTREAM Method (BLOB)

There are several industry text encoding formats and different systems support different formats. Internally,
Dynamics 365 Business Central uses Unicode encoding. For exporting and importing data with an XMLport, it
supports MS-DOS, UTF-8, UTF-16, and Windows encoding formats.
Data is imported and exported as follows:
When data is imported from an external file, it's read using the format that is specified by the
TextEncoding property or parameter, and then converted to Unicode in Dynamics 365 Business Central.
When data is exported to an external file, it's converted from Unicode in Dynamics 365 Business Central,
and then written to the file in the format that is specified by the TextEncoding property or parameter.
You should set the text encoding to the encoding format that is compatible with the system or program that
you'll be exporting to or importing from. The following sections describe the available text encoding formats.
MS -DOS encoding format
MS-DOS encoding, which is also referred to as OEM encoding, is an older format than UTF-8 and UTF-16, but
it's still widely supported.
MS-DOS encoding requires a different character set for each language. When the property is set to MS-DOS,
text is encoded by using the system locale language of the computer that is running Business Central Server
instance. So if you use MS-DOS encoding, you should set the system locale language of server instance
computer to match the language of the data that is being imported or exported. For example, if an XMLport
includes text in Danish, then you should set the system locale language of the server instance computer to
Danish before the XMLport is run.
You should choose MS-DOS with XMLports that were created in earlier versions of Dynamics 365 Business
Central.
UTF -8 encoding format
UTF-8 encoding is a Unicode Transformation Format that uses one byte (8 bits) to encode each character. UTF-8
is based on the Unicode character set, which includes most characters of all languages in a single character set.
Unlike MS-DOS, when you use UTF-8, you don't have to consider the language settings of Business Central
Server instance or the external system or program that will read or write the data.
UTF-8 is compatible with ASCII so that it will understand files written in ASCII format.
UTF-8 is the most common encoding format and the recommended setting if you aren't sure of the format that
is supported by the system that you're integrating with.
UTF -16 encoding format
UTF-16 encoding resembles UTF-8 except that UTF-16 uses 2 bytes (16 bits) to encode each character. UTF-16
is also based on the Unicode character set, so you don't have to consider the language setting of Business
Central Server instance or the external system or program that reads or writes the data.
UTF-16 includes two encoding schemes, which mandate the byte order: UTF-16LE and UTF-16BE. The schemas
are supported as follows:
When exporting, the file is written using UTF-16LE encoding.
When importing, the file is read using the UTF-16, UTF-16LE, or UTF-16BE, depending on encoding
scheme of the file itself.
A UTF-16 encoded file will typically be larger than the same file encoded with UTF-8, except for Eastern
language character sets, which will typically be smaller.
UTF-16 is incompatible with ASCII so that it will not understand files written in ASCII format.
Windows format
Windows encoding is also referred to as ANSI encoding. If you set the text encoding to Windows , you can
import and export text files that are based on the Windows codepage determined by the system locale on the
Business Central Server. As a result, you don't have to consider the language setting of Business Central Server
instance computer or the external system or program that reads or writes the data.
For example, if an XMLport can import bank files from a foreign bank in addition to a domestic bank, use
Windows encoding instead of MS-DOS encoding to avoid changing the language of the Business Central Server
instance computer.

NOTE
In Business Central online, you have no control over the system locale on Business Central Server. Here, it's recommended
to use UTF8/UTF16 for text encodings instead.
See Also
TextEncoding Property (XMLports)
File Data Type
FlowFields
2/6/2023 • 2 minutes to read • Edit Online

FlowFields display the result of the calculation described in the CalcFormula Property. For example, the Account
Balance field in the General Ledger Account table shows the balance of the account and is calculated as the sum
of the NetAmount fields for all General Journal entries in the account.
FlowFields increase performance in activities such as calculating the balance of your customers. In traditional
database systems, this involves a series of accesses and calculations before a result is available. By using
FlowFields, the result is immediately available. You can further optimize the performance of Flowfields by
enabling or disabling SIFT. For more information, see SumIndexField Technology (SIFT).
FlowFields are not physical fields that are stored in the database. They are a description of a calculation and a
location for the result to be displayed. Because the information in FlowFields exists only at run time, values in
FlowFields are automatically initialized to 0 (zero). To update a FlowField, use the CalcFields Method (Record). If a
FlowField is the direct source expression of a control on a page, then the FlowField is automatically calculated
when the page is displayed.

FlowField types
There are seven types of FlowFields. Each is described in the following table.

F LO W F IEL D T Y P E F IEL D T Y P E DESC RIP T IO N

Sum Decimal, Integer, BigInteger, or The sum of a specified set in a column


Duration in a table.

Average Decimal, Integer, BigInteger, or The average value of a specified set in


Duration a column in a table.

Exist Boolean Indicates whether any records exist in


a specified set in a table.

Count Integer The number of records in a specified


set in a table.

Min Any The minimum value in a column in a


specified set in a table.

Max Any The maximum value in a column in a


specified set in a table.

Lookup Any Looks up a value in a column in


another table.

Example
Consider the Customer table in the following illustration. This table contains two FlowFields. The field named
Any Entries is a FlowField of the Exist type, and the Balance field is a FlowField of the Sum type.
The figure shows that the value in the Balance FlowField for customer number 10000 (Windy City Solutions) is
retrieved from the Amount column in the Customer Entry table. The value is the sum of the amount fields for
the entries that have the customer number 10000.

Sum = 10 + 20 + 30 = 60.

The values shown in the Balance column in the Customer table for customers 10010, 10020, and 10040 are
found in the same way. For customer number 10030 the value is 0 (zero), as there are no entries in the
Customer Entry table that have a Customer No. that equals 10030.
In this example, the Balance FlowField in the Customer table reflects the sum of a specific subset of the Amount
fields in the Customer Entry table. How the calculation of a FlowField is to be made, is defined in a calculation
formula. The calculation formula for the Balance field is:

Sum("Customer Entries".Amount WHERE(CustNo=FIELD(CustNo)))

Correspondingly, the Any Entries field, which indicates whether any entries exist, has the following definition:

Exist("Customer Entries" WHERE(CustNo=FIELD(CustNo)))

See Also
CalcFields Method (Record)
Create FlowFields and FlowFilters
Create FlowFields and FlowFilters
2/6/2023 • 3 minutes to read • Edit Online

This topic describes the procedure and the properties used to create FlowFields and FlowFilters.
A FlowField performs a set of calculations and displays the results immediately. A FlowFilter displays the results
based on the user input to calculate the filtered values that will affect the calculation of a FlowField. The
FlowFields and FlowFilters are not physical fields; these fields act as a virtual field which does not actually exist
in the database. They are a description of a calculation and a location for the result to be displayed which is
typically derived in the CalcFormula Property.
For more information about the FlowField type, see FlowFields, and for more information about the FlowFilter
type, see FlowFilter Overview.

Classifying the field type


In order to create FlowFields and FlowFilters, you must first classify the field type by using the FieldClass
Property. For more information, see FieldClass Property. By classifying the field as a FlowField or a FlowFilter
type, you enable the fields to act as a virtual field whose value can be dynamically derived based on the
calculation formula.

Calculation formula
A FlowField type is always associated with a calculation formula that determines how the FlowField is calculated.
Likewise, the FlowFilter type is associated with the calculation formula. To perform the calculations by using the
FlowField and FlowFilter type, you must derive those fields in the calculation formula which you classify in the
table. You can choose from several methods of calculations including sum (total), average, maximum value,
minimum value, record count, lookup, and more, by using the CalcFormula Property. For more information
about the syntax and formulas, see Calculation Formulas and the CalcFormula Property.
Example
In the following example, MyTable sets the Global Dimension 1 Filter and Global Dimension 2 Filter fields
whose values are based only on the dimension values included in the filter. Also, some of the following fields
formulate the currency filter to one single currency because you do not store the filter value on the entries,
hence you define the Currency Filter as a FlowFilter type. Total Amount , Amount upper bound ,
Amount lower bound , First Entry , and Customer Balance are classified as a FlowField type and here you specify
the calculations. These fields display the results immediately based on the filters that you apply in the user
interface.

table 50123 MyTable


{
fields
{
field(1;MyField; Decimal)
{
Description='New field';
}

field(2;"No."; Code[20])
{
Description='Serial number of the service';
}

field(3;"Global Dimension 1 Filter"; Code[20])


field(3;"Global Dimension 1 Filter"; Code[20])
{
FieldClass = FlowFilter;
}

field(4;"Global Dimension 2 Filter"; Code[20])


{
FieldClass = FlowFilter;
}

field(5;"Currency Filter"; Code[10])


{
FieldClass = FlowFilter;
}

field(6; "Total Amount"; Decimal)


{
FieldClass = FlowField;
CalcFormula = Sum("Detailed Cust. Ledg. Entry"."Amount (LCY)"
WHERE ("Customer No."=Field("No."),
"Initial Entry Global Dim. 1"=Field("Global Dimension 1 Filter"),
"Initial Entry Global Dim. 2"=Field("Global Dimension 2 Filter"),
"Currency Code"=Field("Currency Filter")
) );
}

field(7; "Amount upper bound"; Decimal)


{
FieldClass = FlowField;
CalcFormula = max ("Detailed Cust. Ledg. Entry"."Amount (LCY)"
WHERE ("Customer No." = Field ("No."),
"Initial Entry Global Dim. 1" = Field ("Global Dimension 1 Filter"),
"Initial Entry Global Dim. 2" = Field ("Global Dimension 2 Filter"),
"Currency Code" = Field ("Currency Filter")
));
}

field(8; "Amount lower bound"; Decimal)


{
FieldClass = FlowField;
CalcFormula = min ("Detailed Cust. Ledg. Entry"."Amount (LCY)"
WHERE ("Customer No." = Field ("No."),
"Initial Entry Global Dim. 1" = Field ("Global Dimension 1 Filter"),
"Initial Entry Global Dim. 2" = Field ("Global Dimension 2 Filter"),
"Currency Code" = Field ("Currency Filter")
));
}

field(9; "First entry"; Boolean)


{
CalcFormula = exist (Customer where (Payments = const (0),
"No." = field ("No.")));
FieldClass = FlowField;
Caption = 'Specifies whether it is the customer''s first entry';
}

field(10; "Customer Balance"; Decimal)


{
FieldClass = FlowField;
CalcFormula = lookup (Customer.Balance where ("No." = field ("No.")));
}
}
}

See Also
FlowFields
FlowFilter Overview
Calculation Formulas and the CalcFormula Property
Nonclustered Columnstore Indexes
2/6/2023 • 2 minutes to read • Edit Online

Nonclustered columnstore indexes (NCCIs) let you quickly calculate the sums of numeric data type (Decimal,
Integer, BigInteger, and Duration) columns in tables. Calculations can be done in tables with millions of records.
NCCIs optimize the performance of FlowFields and query results in a Business Central application. The articles in
this section describe how NCCIs are implemented in Business Central.

See Also
NCCI and SQL Server
NCCI Tuning and Tracing
NCCI Performance
Migrating from SIFT to NCCI
FlowFields
Nonclustered Columnstore Indexes and SQL Server
2/6/2023 • 2 minutes to read • Edit Online

A nonclustered columnstore index (NCCI) is always associated with a table, and there can only be one defined
per table.
Any field that exists in the table, except BLOB data types, can be added to the NCCI.

Implementing NCCI
In contrast to SIFT keys, which rely on the indexed views feature in SQL Server, NCCIs in Business Central use
only the nonclustered columnstore indexes feature. No aggregated data is stored in the NCCI—all analytical
queries are done at runtime. This implementation also means you don't have to worry about the order of fields
added to the NCCI or design specific NNCIs for specific flow field scenarios.
With SIFT keys, any insert, update, or delete operations to the underlying table will introduce some database
locking because the indexed views must be updated as well. The more SIFT keys that are defined on the table,
the more index maintenance is needed. This problem doesn't exist with a nonclustered columnstore index.

See Also
NCCI Overview)
NCCI Tuning and Tracing
NCCI Performance
Migrating from SIFT to NCCI
Nonclustered Columnstore Indexes Tuning and
Tracing
2/6/2023 • 2 minutes to read • Edit Online

Nonclustered columnstore (NCCIs) indexes are exposed to SQL Server tracing and tuning tools. For example, the
SQL Server profiler can display information about which columnstore indexes are used in the system. This
information makes it easy for you to assess the cost of maintaining an NCCI. It allows you to make informed
decisions about any adjustments that might be required.

SIFT keys versus NCCIs


When data is inserted, updated, or deleted in a table, the SIFT keys that are defined and enabled for that table
are maintained. Maintaining these SIFT indexes has performance overhead. The size of the performance
overhead depends on the number of keys and SumIndexFields that have been defined for each table. So give
careful consideration to the number of SIFT keys that you define. Only maintain the SIFT keys that are important
for your application.
With an NCCI, only one index structure exists and needs to be maintained. So there's no need to consider which
query scenarios should be indexed.

See Also
NCCI Overview)
NCCI and SQL Server
NCCI Performance
Migrating from SIFT to NCCI
SumIndexField Technology (SIFT)
FlowFields
Nonclustered Columnstore Indexes and
Performance
2/6/2023 • 2 minutes to read • Edit Online

This article looks at the factors you must take into consideration when you deal with nonclustered columnstore
indexes (NCCIs) and performance.

Performance factors to consider


The factors that you must take into consideration when you deal with any performance problems that arise
include:
Do you need an NCCI at all (is it being used)?
Which fields do you need to index?
Can you disable some or all SIFT indexes and just use an NCCI?

IMPORTANT
Remember to perform tests every time you make any changes to the NCCI structure. You must ensure that the changes
that you have made don't cause problems in any other areas of the application. You must also ensure that your changes
don't have a negative effect on performance.

See Also
NCCI Overview)
NCCI and SQL Server
NCCI Tuning and Tracing
Migrating from SIFT to NCCI
FlowFields
Migrating from SIFT to Nonclustered Columnstore
Indexes
2/6/2023 • 2 minutes to read • Edit Online

The nonclustered columnstore index (NCCI) is envisioned to be the successor of SumIndexField Technology
(SIFT). This article provides examples of how to replace one or more SIFT keys on a table with a nonclustered
columnstore index.

Why migrating from SIFT Keys to NCCIs


When data is inserted, updated, or deleted in a table, the SIFT keys for that table are maintained. Maintaining
these SIFT indexes has performance overhead. The size of the performance overhead depends on the number of
keys and SumIndexFields that have been defined for each table. So give careful consideration to the number of
SIFT keys that you define. And only maintain the SIFT keys that are important for your application.
With an NCCI, only one index structure exists and needs to be maintained. So there's no need to consider which
query scenarios should be indexed.

Example
This example illustrates how to replace SIFT indexes on a table with an NCCI.
The following code creates a table with two SIFT keys defined on it. The Student table is a simple model of
students with counts of ECTS points and how many courses they've passed.
table 50100 Student
{
DataClassification = CustomerContent;

fields
{
field(1; ID; Integer)
{
DataClassification = EndUserPseudonymousIdentifiers;
}
field(2; Code; Text[50])
{
DataClassification = EndUserPseudonymousIdentifiers;
}
field(3; FirstNames; Text[100])
{
DataClassification = EndUserIdentifiableInformation;
}
field(4; ECTSPoints; Integer)
{
DataClassification = CustomerContent;
}
field(5; NumberOfCourses; Integer)
{
DataClassification = CustomerContent;
}
}

// Here are the SIFT keys that the developer added to the table:
keys
{
// Defines the primary key
key(PK; ID)
{
Clustered = true;
}
// Defines a SIFT index on Code with aggregations fields for count and SUM(ECTSPoints)
key(SIFTKeyOnCode; Code)
{
SumIndexFields = ECTSPoints;
MaintainSqlIndex = false;
}
// Defines a SIFT index on FirstNames with aggregations fields for count and SUM(NumberOfCourses)
key(SIFTKeyOnNames; FirstNames)
{
SumIndexFields = NumberOfCourses;
MaintainSqlIndex = false;
}
}
}

To replace SIFT keys with an NCCI, just add all fields to the definition of the NCCI and remove the SIFT keys:
table 50100 Student
{
DataClassification = CustomerContent;
// Defines NCCI to replace the SIFT keys
ColumnStoreIndex = Code,FirstNames,ECTSPoints,NumberOfCourses;

fields
{
field(1; Code; Text[50])
{
DataClassification = EndUserPseudonymousIdentifiers;
}
field(2; FirstNames; Text[100])
{
DataClassification = EndUserIdentifiableInformation;
}
field(3; ECTSPoints; Integer)
{
DataClassification = CustomerContent;
}
field(4; NumberOfCourses; Integer)
{
DataClassification = CustomerContent;
}
}
keys
{
// Defines the primary key
key(PK; ID)
{
Clustered = true;
}
}
}

See Also
SumIndexField Technology (SIFT)
SIFT and SQL Server
SIFT Tuning and Tracing
SIFT Performance
NCCI Overview)
NCCI and SQL Server
NCCI Tuning and Tracing
NCCI Performance
SumIndexField Technology (SIFT)
2/6/2023 • 2 minutes to read • Edit Online

SumIndexField Technology (SIFT) lets you quickly calculate the sums of numeric data type (Decimal, Integer,
BigInteger, and Duration) columns in tables, even in tables with thousands of records. SIFT is used to optimize
the performance of FlowFields and query results in a Business Central application. SIFT involves performing a
series of database calls and calculations before arriving at a result. The topics in this section describes how SIFT
is implemented in Business Central.

See Also
SIFT and SQL Server
SIFT Tuning and Tracing
SIFT Performance
Migrating from SIFT to NCCI FlowFields
SIFT and SQL Server
2/6/2023 • 2 minutes to read • Edit Online

A SumIndexField is always associated with a key and each key can have a maximum of 20 SumIndexFields
associated with it. In this topic, a key that has at least one SumIndexField associated with it is a SIFT key.

IMPORTANT
Any field that has a numeric data type of Decimal, Integer, BigInteger, or Duration, can be associated with a key as a
SumIndexField.

Implementing SIFT
Business Central uses Indexed Views to maintain SIFT totals. Indexed views are a standard SQL Server feature.
An indexed view is like a SQL Server view except that the contents have been materialized (computed and
stored) to speed up the retrieval of data. For more information about indexed views, see SQL Server
Documentation.
Business Central creates one indexed view for each SIFT key that is enabled. When you create a SIFT key for a
table, you must set the MaintainSIFTIndex Property for that key to True to enable the SIFT key and create the
indexed view. After SQL Server has created the indexed view, it maintains the contents of the view when any
changes are made to the base table. If you set the MaintainSIFTIndex Property for that key to False , SQL Server
drops the indexed view and stops maintaining the totals.
The indexed view that is generated for a SIFT key is always created at the level of finest granularity. Therefore, if
you create a SIFT key for AccountNo., PostingDate , the database will store an aggregated value for each account
for each date. This means that in the worst case scenario, 365 records must be summed to generate the total for
each account for a year.
The following is an example of how Business Central creates an indexed view for a SIFT key that consists of the
AccountNo. and PostingDate fields with a total for the Amount field.

CREATE VIEW GLEntry$VSIFT$1 AS


SELECT SUM(Amount) as SUM$Amount, AccountNo, PostingDate
FROM GLEntry
GROUP BY AccountNo, PostingDate
;

CREATE UNIQUE CLUSTERED INDEX VSIFTIDX ON


GLEntry$VSIFT$1(AccountNo, PostingDate)
;

The following AL code example retrieves a total.

GLEntry.SetCurrentKey("G/L Account No.", "Posting Date");


GLEntry.SetRange("G/L Account No.", '1110');
GLEntry.SetRange("Posting Date", DMY2Date(1,1,2007), DMY2Date(15,12,2007));
GLEntry.CalcSums(Amount);

The following code example shows how the same total is retrieved through an indexed view.
SELECT SUM(SUM$Amount)
FROM GLEntry$VSIFT$1 WITH(NOEXPAND)
WHERE AccountNo=?
AND PostingDate>=?
AND PostingDate<=?

See Also
SumIndexField Technology (SIFT)
Tuning and Tracing
SIFT and Performance Migrating from SIFT to NCCI
SIFT Tuning and Tracing
2/6/2023 • 2 minutes to read • Edit Online

As a result of using indexed views, SIFT keys are exposed to SQL Server tracing and tuning tools. For example,
the SQL Server profiler can display information about which indexed views are maintained for a specific table.
This makes it easy for you to assess the cost of maintaining SIFT keys and allows you to make informed
decisions about any adjustments that might be required.

SIFT Keys
When data is inserted, updated, or deleted in a table, the SIFT keys that have been defined and enabled for that
table are maintained. Maintaining these SIFT indexes has performance overhead. The size of the performance
overhead depends on the number of keys and SumIndexFields that have been defined for each table. You should
therefore give careful consideration to the number of SIFT keys that you define and only maintain the SIFT keys
that are important for your application.
There is no need to maintain a SIFT key for a total that is only used periodically and can be easily generated by a
report. You can still program Business Central to calculate the SIFT based totals even if the SIFT key is disabled.
The calculation is performed directly on the base table.
You should consider combining indexes wherever possible.

Example
Maintaining two SIFT keys:
1. Key: "WareHouseId, ItemId, Color" SumField: "OnStock"
2. Key: "WareHouseId, ItemId, Size" SumField: "OnStock"
If there are only a few combinations of Size and Color (for example, less than 200), then one combined
index/SIFT key should be sufficient.
1. The Combined Key:
2. "WareHouseId, ItemId, Color, Size" SumFIeld: "OnStock"
When you set the MaintainSIFTIndex Property of a key to True , this will be the SIFT key and create the indexed
view to support it. However, disabling the SIFT key by setting MaintainSIFTIndex Property to False can improve
performance in certain circumstances. Setting this property to False means that the SIFT functionality must be
implemented by calculating the totals online instead of using the precalculated sums that are maintained by
SIFT.

See Also
SumIndexField Technology (SIFT)
SIFT and SQL Server
SIFT Performance Migrating from SIFT to NCCI FlowFields
SIFT and Performance
2/6/2023 • 2 minutes to read • Edit Online

This topic looks at the factors you must take into consideration when you deal with SIFT and performance.

Performance Factors to Consider


The factors that you must take into consideration when you deal with any performance problems that arise
include:
Designing your SIFT indexes optimally.
Supporting too many SIFT indexes will affect performance.
Having unnecessary date fields in the SIFT indexes of the base table will affect performance because they
create three times as many entries as an ordinary field.
Supporting too many fields in the SIFT indexes will also affect performance.
The fields in the SIFT index that are used most regularly in queries must be positioned to the left in the
SIFT index. Usually, the field that contains the greatest number of unique values must be placed on the
left, with the field that contains the second greatest number of unique values on the right and so on.
Integer fields generally contain the greatest number of unique values and Option fields contain a
relatively small number of values.
Consider the costs and the benefits of maintaining SIFT indexes.

C O ST B EN EF IT

Updates to the SIFT indexes Fast calculation of sums

Potential locking conflicts

You can prevent the SIFT indexes from being updated by setting the MaintainSIFTIndex Property of the index in
the base table to False . This means that you no longer benefit from SIFT's ability to calculate sums quickly.
However, the SIFT functionality is still available. If the base table does not grow or only grows slowly, there is no
need to set the MaintainSIFTIndex Property to True for any indexes that contain SumIndexFields. If the base
table does grow, you should set the MaintainSIFTIndex Property to True for any indexes that contain
SumIndexFields.
In Business Central , changes have been made to improve performance when accessing the database. One of
these changes is that Business Central automatically maintains a count for all SIFT indexes. For more
information about how this affects the Count and Average methods on FlowFields, see CalcFields Method. For
more information about other data access changes, see Data Access.
IMPORTANT
It is important that you remember to perform tests every time you make any changes to the SIFT structures. You must
ensure that the changes that you have made do not cause problems in any other areas of the application. You must also
ensure that your changes do not have a negative effect on performance.

See Also
SumIndexField Technology (SIFT)
SIFT and SQL Server
SIFT Tuning and Tracing
Migrating from SIFT to NCCI FlowFields
Number Sequences in Business Central
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

In AL, you can create and manage number sequences that generate numeric identifiers for data and records.
Business Central number sequences are built on SQL Server sequences, which means that they are not
associated with any tables. Instead, the application code references the number sequence object and coordinates
the values across records.
The numbers in a number sequence are generated in ascending order at a defined interval. Numbers are used
sequentially, but numbers can be skipped. This means that numbers used on records in tables can have gaps.
These gaps, for example, can occur when transactions are rolled back or numbers are allocated but not used.

Number sequences and number series in the application


Unlike number sequences, number series are specially designed for scenarios where you have to use a
continuous numbering system on transactional records. This typically includes documents such as purchase
orders, sales orders, and invoices. The drawback of using continuous numbers is that when a number is
requested by a transaction, the No Series Line table in the database is locked until the transaction completes.
This can potentially block other users from being able to work.
For more information about number series, see Create Number Series in the Business Central application help.

Using non-blocking number series for improved performance


Number series also include an option called Allow Gaps in Nos.. This option actually uses number sequences
in the underlying code, and allows you to implement non-continuous, non-blocking numbering. So, if there are
no regulatory requirements for using continuous numbering, you can improve performance by allowing gaps
and using a number sequence instead. Customer cards, sales quotes, and warehouse activities are examples of
entities that typically do not require continuous numbering.

Creating and managing number sequences in AL


To create and manage number sequences, you use the NumberSequence data type and the following methods.

M ET H O D N A M E DESC RIP T IO N

[Insert(String, BigInteger][, BigInteger], [Boolean]) Creates a number sequence in the database, with the given
parameters.

Exists(String[, Boolean]) Checks whether a specific number sequence exists.

Delete(String[, Boolean]) Deletes a specific number sequence.

Next(String[, Boolean]) Retrieves the next value from the number sequence.
M ET H O D N A M E DESC RIP T IO N

Current(String[, Boolean]) Gets the current value from the number sequence, without
doing any increment. The value is retrieved out of
transaction. The value will not be returned on transaction
rollback.

Examples

// Creates a NumberSequence object that starts with the value '0' and increments by '1'
NumberSequence.Insert('DefaultSequence');

// Creates a NumberSequence object that starts with the value '10' and increments by '1'
NumberSequence.Insert('StartsWithTenSequence', 10);

// Creates a NumberSequence object that starts with the value '0' and increments by '10'
NumberSequence.Insert('StartsWithZeroIncrementTenSequence', 0, 10);

// Creates a NumberSequence object that starts with the value '0', increments by '1', and is company-
specific
NumberSequence.Insert('MyCompanySequence', 0, 1, true);

// Verifies whether a specific NumberSequence object exists, and if so, deletes it

if NumberSequence.Exists('MySequence', true) then


NumberSequence.Delete('MySequence',true);

// Gets and returns the current value in a NumberSequence object


number := NumberSequence.Current('MySequence',true);

// Gets and returns the next value in a NumberSequence object


number := NumberSequence.Next('MySequence',true);

See Also
Number Sequence data type
SQL Server Sequences
Extensible Enums
2/6/2023 • 4 minutes to read • Edit Online

An enumeration type, also known as an enum in programming, is a keyword used to declare a type that consists
of a set of named constants. The list of named constants is called the enumeration list. Enums can be used as
table fields, local and global variables, and parameters.
To declare an enum in AL you must specify an ID and a name. The enumeration list consists of values and each
of the values are declared with an ID and a value. The value ID is the ordinal value on the enumeration list and
must be unique. When the enum values are displayed in the UI they're sorted by the order of declaration. In
addition, if extension B extends extension A , the enum values declared in extension A are displayed before the
enum values declared in extension B .
The following example shows the declaration of an enum, which can be extended, and has the four values;
None , Bronze , Silver , and Gold .

enum 50121 Loyalty


{
Extensible = true;

value(0; None) { }
value(1; Bronze) { }
value(2; Silver) { }
value(3; Gold)
{
Caption = 'Gold Customer';
}
}

NOTE
While enums and enumextension objects have object IDs, these are not enforced by the license. In previous versions they
reused the range for tables, and were checked against the license at deployment time, but this is no longer the case.
Uniqueness validation is now enforced during installation, which will fail if an enum object ID clashes with an already
installed enum. Thus, as always, it is important that you use object IDs in your assigned range. This is enforced for
AppSource apps, but not for per-tenant extensions, or on-premise. The enum does not have to use the same ID as the
table it is put on.

IMPORTANT
Only enums with the Extensible Property set to true can be extended.

IMPORTANT
When creating captions for enums, it's important that the caption doesn't contain a comma. Having a comma in the
caption, such as Caption = 'Diamond Level, with bonus' , can display over multiple lines in the UI. This behavior also
causes that the actual value selected by the user in the UI, doesn't correspond to the value, which is saved in the
database.
An AppSourceCop warning will be triggered if .xlf files contain commas in enum captions. For more information, see
AppSourceCop Warning AS0087.
Enumextension object
Enums can be extended in order to add more values to the enumeration list in which case the Extensible
property must be set to true . The syntax for an enum extension, which extends the Loyalty enum with the
value Diamond , is shown below.

enumextension 50130 LoyaltyWithDiamonds extends Loyalty


{
value(50130; Diamond)
{
Caption = 'Diamond Level';
}
}

Usage
When referencing a defined enum from code, you use the syntax as illustrated below.
enum Loyalty

If you want to define an enum as a table field type, use the syntax illustrated below:

field(50100; Loyal; enum Loyalty) {}

Or, as a variable:

var
LoyaltyLevel: enum Loyalty;

In code, you address a specific enum value like in the following example:

codeunit 50140 EnumUsage


{
procedure Foo(p: enum Loyalty)
var
LoyaltyLevel: enum Loyalty;
begin
if p = p::Gold then begin
LoyaltyLevel := p;
end;
end;
}

Example
The following example illustrates how to define an enum extension of TypeEnum , using it in a table extension
TableWithRelationExt and displaying it as a control on a new page.
enumextension 50133 TypeEnumExt extends TypeEnum
{
value(10; Resource) { }
}

tableextension 50135 TableWithRelationExt extends TableWithRelation


{
fields
{
modify(Relation)
{
TableRelation = if (Type = const (Resource)) Resource;
}
}
}

page 50133 PageOnRelationTable


{
SourceTable = TableWithRelation;
SourceTableView = where (Type = const (Resource));
PageType = List;

layout
{
area(Content)
{
repeater(MyRep)
{
field(Id; Id)
{
ApplicationArea = All;
}
field(Type; Type)
{
ApplicationArea = All;
}
field(Relation; Relation)
{
ApplicationArea = All;
}
}
}
}
}

TIP
For another example of how to extend the usage of the TableRelation property in connection with enums, see
TableRelation Property.

Business Central on-premises


If you want to extend an existing Dynamics 365 on-premises enum, it's possible to mark a table field in C/SIDE
as extensible. To enable running C/SIDE and AL side-by-side, see Running C/SIDE and AL Side-by-Side.
Table field options in C/SIDE have three properties to enable enum support:

P RO P ERT Y N A M E DATA T Y P E

Extensible Boolean, default value is No .


P RO P ERT Y N A M E DATA T Y P E

EnumTypeId Integer

EnumTypeName Text

Some table fields share options that are semantically identical. In those cases, the EnumTypeId and
EnumTypeName must be the same across all the fields. There's no design or runtime check for collision of IDs,
but loading generated symbols, see Running C/SIDE and AL Side-by-Side, into the compiler will show collision
errors.
Conversions
Conversion to and from enum is more strict than for Options in C/SIDE.
An enum can be assigned/compared to an enum of the same type.
To be backwards compatible, we support conversion to/from any Option for now.

For information about assignment compatibility, see AssignmentCompatibility Property.

See Also
AL Data Types
TableRelation Property
Extensible Property
Enum Data Type
AssignmentCompatibility Property
Protected Variables
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

The protected keyword can be used to make variables accessible between tables and table extensions and
between pages and page extensions. If you want to only expose some variables as protected , you must create
two sections of var declarations. See the syntax below.

Syntax
protected var
myInt: Integer; // protected var

var
myLocalInt: Integer; // local var

Example
The example below illustrates how to declare and use a protected variable.

page 50100 MyPage


{
SourceTable = Customer;
PageType = Card;

layout
{
area(Content)
{
group(General)
{
field(Name; Name)
{
ApplicationArea = All;
}
}
group(Advanced)
{
Visible = ShowBalance;

field(Balance; Balance)
{
ApplicationArea = All;
}
}
}
}

protected var
[InDataSet]
ShowBalance: Boolean;
}

pageextension 50101 MyPageExt extends MyPage


{
layout
layout
{
addlast(Content)
{
group(MoreBalance)
{
Visible = ShowBalance; // ShowBalance from MyPage

field("Balance (LCY)"; "Balance (LCY)")


{
ApplicationArea = All;
}
}
}

actions
{
addlast(Navigation)
{
action(ToggleBalance)
{
ApplicationArea = All;
trigger OnAction()
begin
ShowBalance := not ShowBalance; // Toggle ShowBalance from MyPage.
end;
}
}
}
}

See Also
AL Method Reference
Properties
Access Property
Extensible Property
Working with Labels
2/6/2023 • 2 minutes to read • Edit Online

Labels are string constants displayed in the Business Central client that can be translated into multiple
languages, such as captions, descriptions, or messages. This way, the user interface can be displayed in different
languages. For more information on how translation is carried out in Dynamics 365 Business Central, see
Multilanguage development.

Label syntax
Labels have a specific syntax defined by a text constant followed by three optional parameters. They must be
comma-separated, but the order of the parameters is not enforced. The parameters that you can set are
described in the following table.

PA RA M ET ER TYPE DESC RIP T IO N

Comment Text Used for general comments about the


label, specifically about the
placeholders in that label.

Locked Boolean When Locked is set to true , the label


should not be translated. Default value
is false .

MaxLength Integer Determines how much of the label is


used. If no maximum length is
specified, the string can be any length.

Using labels
A label can take the form of four different AL structures. It can be the property value of certain page and report
properties, the label data type variable and a report or a page label. The different possibilities are explained in
more detail below.
Properties
The label syntax is used in properties that are set to display text on the user interface. It applies to the following
properties:
Caption Property
ToolTip Property
OptionCaption Property
AdditionalSearchTerms Property
InstructionalText Property
PromotedActionCategories Property
RequestFilterHeading Property
The following example shows the label syntax when it is used as property value for the Caption property.

Caption = 'Developer translation for %1', Comment = '%1 is extension name', locked = false, MaxLength=999;
Label data type
The Label Data Type denotes a string variable used to define error messages, questions, captions, tokens, or
other text constants displayed to the user.
The following code sample illustrates how to use the Label data type.

var
a:Label'LabelText',Comment='Foo',MaxLength=999,Locked=true;

The Label variable names should have an approved suffix. For more information, see CodeCop Rule AA0074.
Report labels
Report labels are used by RDL and Word report layouts as, for example, the caption for a field, the title for a
chart, or the title for the report itself. For a code example on how to use report labels for an RDL layout, see
Walkthrough: Designing a Report from Multiple Tables.
Report labels are defined inside the labels control of a report object, as shown in the code sample below.

labels
{
LabelName1='LabelText1',Comment='Foo',MaxLength=999,Locked=true;
LabelName2 = 'LabelText2',Comment='Foo',Locked=false;
}

Page labels
Page labels are used to display plain text on a page, such as instructions or informative texts. You can find
several examples of page labels in the Rapidstart Services Wizard in page "Config. Wizard" .
Page labels are defined by a label(Name) control inside the area(Content) part of a page. The following code
shows how to define a page label.

label(BeforeSetupCloseMessage)
{
ApplicationArea = Basic, Suite;
Caption = 'If you still need to change setup data, do not change the profile.'
}

See Also
Working with labels
Working with Translation Files
Label Data Type
Report Layouts
Table Object
2/6/2023 • 2 minutes to read • Edit Online

Tables are the core objects used to store data in Dynamics 365 Business Central. No matter how data is
registered in the product - from a web service to a finger swipe on the phone app, the results of that transaction
will be recorded in a table.
The structure of a table has four sections:
The first block contains metadata for the overall table, such as the table type.
The fields section describes the data elements that make up the table, such as their name and the type of data
they can store.
The keys section contains the definitions of the keys that the table needs to support.
The final section details the triggers and code that can run on the table.

IMPORTANT
Only tables with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

IMPORTANT
System and virtual tables can't be extended. System tables are created in the ID range of 2.000.000.000 and above. For
more information about object ranges, see Object Ranges.

Snippet support
Typing the shortcut ttable will create the basic layout for a table object when using the AL Language extension
in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Table example
This table stores address information and it has four fields; Address , Locality , Town/City , and County .
table 50104 Address
{
Caption = 'Sample table';
DataPerCompany = true;

fields
{
field(1; Address; Text[50])
{
Description = 'Address retrieved by Service';
}
field(2; Locality; Text[30])
{
Description = 'Locality retrieved by Service';
}
field(3; "Town/City"; Text[30])
{
Description = 'Town/City retrieved by Service';
}
field(4; County; Text[30])
{
Description = 'County retrieved by Service';

trigger OnValidate();
begin
ValidateCounty(County);
end;

}
}
keys
{
key(PrimaryKey; Address)
{
Clustered = TRUE;
}
}

var
Msg: Label 'Hello from my method';

trigger OnInsert();
begin

end;

procedure MyMethod();
begin
Message(Msg);
end;
}

System fields
The Dynamics 365 Business Central platform will automatically add several system fields to tables. For more
information, see System Fields.

See Also
AL Development Environment
Table Overview
Table Extension Object
SqlTimestamp Property
Table Keys
Table, Table Fields, and Table Extension Properties
Table Extension Object
2/6/2023 • 2 minutes to read • Edit Online

The table extension object allows you to add additional fields or to change some properties on a table provided
by the Dynamics 365 Business Central service. In this way, you can add data to the same table and treat it as a
single table. For example, you may want to create a table extension for a retail winter sports store. In your
solution you want to have ShoeSize as an additional field on the customer table. Adding this as an extension
allows you to write code for the customer record and also include values for the ShoeSize .
Along with defining other fields, the table extension is where you write trigger code for your additional fields.
When developing a solution for Dynamics 365 Business Central , you will follow the code layout for a table
extension as shown in the example below.

IMPORTANT
Only tables with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

IMPORTANT
System and virtual tables cannot be extended. System tables are created in the ID range of 2.000.000.000 and above. For
more information about object ranges, see Object Ranges.

IMPORTANT
Extending tables from Dynamics 365 for Sales is currently not supported.

Using a table extension to add a key to the base table


Just like in the table object, you can define keys for fields added in the table extension. But you can also add keys
for fields that only exist on the table you extend, in case you want to extend the keys provided in the base table
definition. See Table Keys for examples on how to define keys in a table extension.

Snippet support
Typing the shortcut ttableext will create the basic layout for a table extension object when using the AL
Language extension in Visual Studio Code.

Properties
Using a table extension allows you to overwrite some properties on fields in the base table. For a list of Table
properties, see Table and Table Extension Properties.
Table extension syntax
tableextension Id MyExtension extends MyTargetTable
{
fields
{
// Add changes to table fields here
}

var
myInt: Integer;
}

Table extension example


This table extension object extends the Customer table object by adding a field ShoeSize , with ID 50116 and the
data type Integer . It also contains a procedure to check if the ShoeSize field is filled in.

tableextension 50115 RetailWinterSportsStore extends Customer


{
fields
{
field(50116;ShoeSize;Integer)
{
trigger OnValidate();
begin
if (rec.ShoeSize < 0) then
begin
message('Shoe size not valid: %1', rec.ShoeSize);
end;
end;
}
}

procedure HasShoeSize() : Boolean;


begin
exit(ShoeSize <> 0);
end;

trigger OnBeforeInsert();
begin
if not HasShoeSize then
ShoeSize := Random(42);
end;
}

See Also
AL Development Environment
Table Overview
Table Object
Table, Table Fields, and Table Extension Properties
Table Keys
Table Keys
2/6/2023 • 12 minutes to read • Edit Online

The database management system, which is SQL Server, uses keys to identify rows in a table. Keys identify the
rows by combining one or more columns of a table. SQL also uses indexes to speed up data retrieval from rows
in a table. This article explains how to create keys and indexes for Business Central tables from AL code.

Keys in AL
In AL, a key definition is a sequence of one or more field IDs from a table. You can define keys in table objects
and table extension objects, depending on the type of key. There are two types of keys: primary and secondary.
Primary keys
A primary key uniquely identifies each record in a table. Every table has a primary key, and there can only
be one primary key per table. Primary keys are defined on table objects only. In SQL, table extension
objects inherit the primary key of the table object they extend (the base table object). So any key that you
define in a table extension object is considered a secondary key.
Secondary keys
Secondary keys create indexes in SQL. They're defined in both table objects and table extension objects.
You can define multiple secondary keys for a single table object and table extension object.
A key in table extension object can include fields from the base table object or the table extension object.
There are some limitations, however. For more information, see Limitations and Restrictions.

Primary keys
The primary key keeps track of data in a table. The primary key is composed of up to 16 fields in a record. The
combination of values in fields in the primary key makes it possible to uniquely identify each record. In AL, the
first key defined in a table object is the primary key. The primary key determines the logical order in which
records are stored, no matter the physical placement of the fields in the table object.
Logically, records are stored sequentially in ascending order and sorted by the primary key. Before adding a new
record to a table, SQL Server checks if the information in the record's primary key fields is unique. If so, it then
inserts the record into the correct logical position. Records are sorted dynamically so the database is always
structurally correct. This sorting allows for fast data manipulation and retrieval.
The primary key is always active. SQL Server keeps the table sorted in primary key order and rejects records
with duplicate values in primary key fields. That's why the values in the primary key must always be unique. It's
not the value in each field in the primary key that must be unique. Instead, it's the combination of values in all
fields that make up the primary key.

NOTE
In the development environment, it's technically possible to create a primary key based on up to 20 fields. However,
because of SQL Server limitations, only the first 16 are used.

Secondary keys
In a table object, any keys defined after the primary key are called secondary keys. All keys defined in a table
extension object are considered secondary keys.
A secondary key is implemented on SQL Server using a structure that is called an index. This structure is like an
index that is used in textbooks. A textbook index alphabetically lists important terms at the end of a book. Next
to each term are page numbers. You can quickly search the index to find a list of page numbers (addresses), and
you can locate the term by searching the specified pages. The index is an exact indicator that shows where each
term occurs in the textbook.
When you define a secondary key and mark it as enabled, an index is automatically maintained on SQL Server.
The index reflects the sorting order that is defined by the key. Several secondary keys can be active at the same
time.
A secondary key can be disabled so that it doesn't occupy database space or use time during updates to
maintain its index. Disabled keys can be re-enabled, although this operation can be time-consuming because
SQL Server must scan the whole table to rebuild the index.
The fields that make up the secondary keys don't always contain unique data. SQL Server doesn't reject records
with duplicate data in secondary key fields. So if two or more records contain identical information in the
secondary key, SQL Server uses the table's primary key to resolve this conflict.

TIP
You can see a list of potential columns that can be indexed and other useful information about them in Business Central
on Database Missing Indexes . For more information on missing indexes, see Missing Indexes in Dynamics 365
Business Central

Unique secondary keys


A key definition includes the Unique property that you can use to create a unique constraint on the table in SQL
Server. A unique key ensures that records in a table don't have identical field values. With a unique key, when
table is validated, the key value is checked for uniqueness. If the table includes records with duplicate values, the
validation fails. Another benefit of unique indexes is providing information to the query optimizer that helps
produce more efficient execution plans.
You can create unique secondary keys that are composed of multiple fields, like with primary keys. In this case,
it's the combination of the values in the secondary key that must be unique. Consider the Customer table, for
example. Suppose you wanted to make sure there are no customers that have the same combination of values
for the Name , Address , and City fields. You could create a unique key for these fields.
Unlike primary keys, it's possible to define multiple unique secondary keys on a table.

NOTE
The Unique property isn't supported in table extension objects.

System keys
There's always a unique secondary key on the SystemId field.
Secondary keys with included fields
INTRODUCED IN: Business Central 2021 release wave 2

With non-clustered secondary keys, you can use the IncludedFields property to add fields that aren't part of the
key itself. In SQL server, these non-key fields correspond to what are called included columns. Using included
fields lets you create indexes that cover more queries, and lets you bypass the maximum number of fields in a
key.
A secondary key with included fields can improve SQL query performance, especially when SQL index contains
all columns in the query, either as key columns or included columns. The performance improves because the
query optimizer can locate all the column values within the index. And, it doesn't access table or clustered index
data, which results in fewer disk I/O operations. For more information about included columns in SQL, see
Create indexes with included columns.
Non-clustered Columnstore keys
INTRODUCED IN: Business Central 2021 release wave 2

Non-clustered columnstore indexes (sometimes referred to as NCCIs) are supported on tables.


With the ColumnStoreIndex property, you create a non-clustered columnstore index on the table in SQL server.
Using a non-clustered columnstore key can improve query performance when doing analytics on large tables.
This index type uses column-based data storage and query processing to achieve gains up to 10 times the query
performance in analytical queries over traditional row-oriented storage. You can also achieve gains up to 10
times the data compression over the uncompressed data size on normal tables.
You can use a non-clustered columnstore index to efficiently run real-time operational analytics on the Business
Central database without the need to define SIFT indexes up front (and without the locking issues that SIFT
indexes sometimes impose on the system.) Whenever you would normally add a SIFT key on fields to do
summation/count operations on, use a non-clustered columnstore key to add all the fields to the index instead.
Example
To illustrate, here's a simple example of replacing two SIFT keys with a single non-clustered columnstore index.
Suppose you already have implemented two SIFT keys:
Key1: "WareHouseId, Color" SumField: "OnStock"
Key2: "WareHouseId, ItemId, Size" SumField: "OnStock"
With a non-clustered columnstore index, you could just have one index defined as:
ColumnStoreIndex = WareHouseId,Color,ItemId,Size,OnStock
For more information, see:
ColumnStoreIndex Property
Columnstore indexes: Overview

Clustered and non-clustered keys


A key definition includes the Clustered property that you use to create a clustered index. A clustered index
determines the physical order in which records are stored in the table. Based on the key value, records are
sorted in ascending order. Using a clustered key can speed up the retrieval of records.
There can be only one clustered index per table. By default the primary is configured as a clustered key.

NOTE
The Clustered property isn't supported in table extension objects.

Sort orders and secondary keys


The following example shows how the primary key influences the sort order when a secondary key is active. The
Customer table includes four entries (records), and the records in the Customer table have two fields: Customer
Number and Customer Name.
The following table includes the key list for the Customer table.

K EY K EY T Y P E DEF IN IT IO N

1 Primary Customer Number

2 Secondary Customer Name

When you sort by the primary key, the Customer table resembles the following table.

C USTO M ER N UM B ER C USTO M ER N A M E

001 Customer C

002 Customer A

003 Customer B

004 Customer C

If you select the secondary key for sorting, then the order is based on the contents of the Customer Name field.
Because the contents of these fields aren't unique, the records must be subsorted according to the primary key.

C USTO M ER N A M E C USTO M ER N UM B ER

Customer A 002

Customer B 003

Customer C 001

Customer C 004

NOTE
The two records that have the same Customer Name value are sorted by Customer Number.

How keys affect performance


Searching for specific data is easier if several keys are defined and maintained for the table that holds the
wanted data. The indexes for each key provide specific views that enable quick and flexible searches. There are
advantages and disadvantages to using many keys, as demonstrated in the following table.

IF Y O U P ERF O RM A N C E IM P RO VES W H EN Y O U P ERF O RM A N C E SLO W S W H EN Y O U

Increase the number of secondary Retrieve data in several different Enter data because indexes for each
keys that are marked as active. sorting sequences because the data is secondary key must be maintained.
already sorted.
IF Y O U P ERF O RM A N C E IM P RO VES W H EN Y O U P ERF O RM A N C E SLO W S W H EN Y O U

Decide to use only a few keys. Enter data because a minimal number Retrieve data. You may have to define
of indexes are maintained. or reactivate the secondary keys to get
the appropriate sorting. Depending on
the size of the database, this operation
can take some time, because the index
must be rebuilt.

The decision whether to use a few or many keys isn't easy. The appropriate keys and the number of active keys
to use is a compromise between maximizing the speed of data retrieval and data updates (operations that insert,
delete, or modify data). In general, it may be worthwhile to deactivate complex keys if they're rarely used.
The overall speed depends on the following factors:
Size of the database.
Number of active keys.
Complexity of the keys.
Number of records in your tables.
Speed of your computer and its hard disk.

Defining new keys


To define keys, add the keys keyword after the fields definition, and then add a key keyword for each key:

keys
{
key(Name1; Fields)
{

}
key(Name2; Fields)
{

}
}

Replace Name with descriptive text that you want to use to identify the key. Replace Field with the name of a
field that you want to use as the key. If you want to include multiple fields in a single key, separate each field
with a comma.
In a table object, the first key keyword defines the primary key. Subsequent key keywords define secondary
keys.

TIP
Starting in Business Central version 18, it is possible to create a table extension that only holds key definitions. You can
utilize this to add keys to tables in the base application or in AppSource extensions, where you don't have ownership of
the table definitions.

The following code illustrates simple examples of a table object and table extension object.
table 50120 MyBaseTable
{
fields
{
field(1; MyBaseField1; Integer)
{
}
field(2; MyBaseField2; Integer)
{
}
}

keys
{
key(PK; MyBaseField1) //primary key
{
Clustered = true;
}
key(Key1; MyBaseField2) //secondary key
{
}
}
}

tableextension 50121 MyBaseTableExt extends MyBaseTable


{
fields
{
field(3; MyExtField1; Integer)
{
}
field(4; MyExtField2; Integer)
{
}
field(5; MyExtField3; Integer)
{
}
}

keys
{
key(ExtKey1; MyExtField1) //secondary key
{
IncludeFields = MyExtField2,MyExtField3;
}
key(ExtKey2; MyBaseField1, MyBaseField2) //secondary key
{
}
// The following key isn't allowed because it contains fields from the base table and the table
extension
//key(ExtKey3; MyBaseField1, MyExtField2)
//{
//}
}
}
tableextension 50122 MyCustomerKeyExt extends Customer
{
// This example illustrates how to use a table extension to add a key on the Customer table from the
base application
keys
{
key(ExtKey1; "No.", "Name", City)
{
}
}
}

Key properties
There are several properties that configure the behavior of a key, such as the Enabled, Clustered, and Unique
properties:

keys
{
key(PrimaryKey; ID)
{
Clustered = true;
}
key(CustomerInfo; Name,Address,City)
{
Unique = true;
}
key(Currency; Currency Code)
{
Enabled = false;
}
}

For a more information about the different key properties, see Key Properties.

Limitations and Restrictions


Keys in table extension objects
In table extension objects, you can define multiple keys, just like in a table object. However, the following
limitations apply:
In Business Central 2020 release wave 2 and earlier, keys in table extension objects can only include fields
from the table extension object itself.
In Business Central 2021 release wave 1 and later, keys in table extension objects can include fields from the
base table object and table extension object. However, a single key can't include fields from both the base
table object and table extension object. In other words, each key must contain fields from either the base
table object or the table extension object.
You can use the same key name in the table extension, unless the key contains fields from the base table
object.
Total number of keys
Up to 40 keys can be associated with a table.
Key modifications
When developing a new version of an extension, be aware of the following restrictions to avoid schema
synchronization errors that prevent you from publishing the new version:
Don't delete primary keys.
Don't add or remove primary key fields, nor change their order.
Don't change properties of existing primary keys.
Don't add more unique keys.
Don't add more clustered keys.
Don't add keys that are fields of the base table.

Identifying keys in code


APPLIES TO: Business Central 2022 release wave 2 and later

When you invoke IntelliSense for table fields, the primary key members are marked with a (PKx) in the
IntelliSense list, where x is a sequential number, which indicates the order of the field in the key. This allows
you to identify the table fields that make up the primary key and the sequency of these fields in the key.

See Also
Key Properties Tables Overview
Table Object
Table Extension Object
SystemId Field
Extensible Enums
2/6/2023 • 4 minutes to read • Edit Online

An enumeration type, also known as an enum in programming, is a keyword used to declare a type that consists
of a set of named constants. The list of named constants is called the enumeration list. Enums can be used as
table fields, local and global variables, and parameters.
To declare an enum in AL you must specify an ID and a name. The enumeration list consists of values and each
of the values are declared with an ID and a value. The value ID is the ordinal value on the enumeration list and
must be unique. When the enum values are displayed in the UI they're sorted by the order of declaration. In
addition, if extension B extends extension A , the enum values declared in extension A are displayed before the
enum values declared in extension B .
The following example shows the declaration of an enum, which can be extended, and has the four values;
None , Bronze , Silver , and Gold .

enum 50121 Loyalty


{
Extensible = true;

value(0; None) { }
value(1; Bronze) { }
value(2; Silver) { }
value(3; Gold)
{
Caption = 'Gold Customer';
}
}

NOTE
While enums and enumextension objects have object IDs, these are not enforced by the license. In previous versions they
reused the range for tables, and were checked against the license at deployment time, but this is no longer the case.
Uniqueness validation is now enforced during installation, which will fail if an enum object ID clashes with an already
installed enum. Thus, as always, it is important that you use object IDs in your assigned range. This is enforced for
AppSource apps, but not for per-tenant extensions, or on-premise. The enum does not have to use the same ID as the
table it is put on.

IMPORTANT
Only enums with the Extensible Property set to true can be extended.

IMPORTANT
When creating captions for enums, it's important that the caption doesn't contain a comma. Having a comma in the
caption, such as Caption = 'Diamond Level, with bonus' , can display over multiple lines in the UI. This behavior also
causes that the actual value selected by the user in the UI, doesn't correspond to the value, which is saved in the
database.
An AppSourceCop warning will be triggered if .xlf files contain commas in enum captions. For more information, see
AppSourceCop Warning AS0087.
Enumextension object
Enums can be extended in order to add more values to the enumeration list in which case the Extensible
property must be set to true . The syntax for an enum extension, which extends the Loyalty enum with the
value Diamond , is shown below.

enumextension 50130 LoyaltyWithDiamonds extends Loyalty


{
value(50130; Diamond)
{
Caption = 'Diamond Level';
}
}

Usage
When referencing a defined enum from code, you use the syntax as illustrated below.
enum Loyalty

If you want to define an enum as a table field type, use the syntax illustrated below:

field(50100; Loyal; enum Loyalty) {}

Or, as a variable:

var
LoyaltyLevel: enum Loyalty;

In code, you address a specific enum value like in the following example:

codeunit 50140 EnumUsage


{
procedure Foo(p: enum Loyalty)
var
LoyaltyLevel: enum Loyalty;
begin
if p = p::Gold then begin
LoyaltyLevel := p;
end;
end;
}

Example
The following example illustrates how to define an enum extension of TypeEnum , using it in a table extension
TableWithRelationExt and displaying it as a control on a new page.
enumextension 50133 TypeEnumExt extends TypeEnum
{
value(10; Resource) { }
}

tableextension 50135 TableWithRelationExt extends TableWithRelation


{
fields
{
modify(Relation)
{
TableRelation = if (Type = const (Resource)) Resource;
}
}
}

page 50133 PageOnRelationTable


{
SourceTable = TableWithRelation;
SourceTableView = where (Type = const (Resource));
PageType = List;

layout
{
area(Content)
{
repeater(MyRep)
{
field(Id; Id)
{
ApplicationArea = All;
}
field(Type; Type)
{
ApplicationArea = All;
}
field(Relation; Relation)
{
ApplicationArea = All;
}
}
}
}
}

TIP
For another example of how to extend the usage of the TableRelation property in connection with enums, see
TableRelation Property.

Business Central on-premises


If you want to extend an existing Dynamics 365 on-premises enum, it's possible to mark a table field in C/SIDE
as extensible. To enable running C/SIDE and AL side-by-side, see Running C/SIDE and AL Side-by-Side.
Table field options in C/SIDE have three properties to enable enum support:

P RO P ERT Y N A M E DATA T Y P E

Extensible Boolean, default value is No .


P RO P ERT Y N A M E DATA T Y P E

EnumTypeId Integer

EnumTypeName Text

Some table fields share options that are semantically identical. In those cases, the EnumTypeId and
EnumTypeName must be the same across all the fields. There's no design or runtime check for collision of IDs,
but loading generated symbols, see Running C/SIDE and AL Side-by-Side, into the compiler will show collision
errors.
Conversions
Conversion to and from enum is more strict than for Options in C/SIDE.
An enum can be assigned/compared to an enum of the same type.
To be backwards compatible, we support conversion to/from any Option for now.

For information about assignment compatibility, see AssignmentCompatibility Property.

See Also
AL Data Types
TableRelation Property
Extensible Property
Enum Data Type
AssignmentCompatibility Property
Page Object
2/6/2023 • 2 minutes to read • Edit Online

Pages are the main way to display and organize visual data in Dynamics 365 Business Central. They are the
primary object that a user will interact with and have a different behavior based on the type that you choose.
Pages are designed independently of the device they are to be rendered on, and in this way the same page can
be reused across phone, tablet, and web clients.
The structure of a page is hierarchical and breaks down in to three sections. The first block contains metadata for
the overall page; the type of the page and the source table it is showing data from. The next section; the layout,
describes the visual parts on the page. The final section details the actions that are published on the page.
When developing a solution for Dynamics 365 Business Central, you will follow the code layout for a page as
shown in the page example below, but for more details on the individual controls and properties that are
available, see Page Property Overview.
If you want to, for example, add functionality to a page that already exists in Business Central, you can create a
page extension object that changes an existing page object. For more information, see Page Extension Object.
Depending on how much you want to change on an existing page, you can also create a page customization
object, which offers modifications on actions and layout. For more information, see Page Customization Object.

IMPORTANT
Only pages with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

Snippet support
Typing the shortcut tpage will create the basic layout for a page object when using the AL Language extension
in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Views
Views in Dynamics 365 Business Central are used on list pages to define a different view of the data on a given
page. Views can be defined for Pages, Page Extensions, and Page Customization. For more information, see
Views.

Page example
page 50101 SimpleCustomerCard
{
PageType = Card;
SourceTable = Customer;
ContextSensitiveHelpPage = 'my-feature';

layout
{
area(content)
{
group(General)
{
field("No."; "No.")
{
ApplicationArea = All;
CaptionML = ENU = 'Hello';

trigger OnValidate()
begin
if "No." < '' then
Message('Number too small')
end;
}

field(Name; Name)
{
ApplicationArea = All;
}
field(Address; Address)
{
ApplicationArea = All;
}
}
}
}
actions
{
area(Navigation)
{
action(NewAction)
{
ApplicationArea = All;
RunObject = codeunit "Document Totals";
}
}
}
}

See Also
AL Development Environment
Views
Adding Help Links from Pages, Reports, and XMLports
Page Extension Object
Page, Page Fields, and Page Extension Properties
Page Properties
Developing Extensions
Configure Context-Sensitive Help
Page Extension Object
2/6/2023 • 4 minutes to read • Edit Online

The page extension object extends a Dynamics 365 Business Central page object and adds or overrides the
functionality.
The structure of a page is hierarchical and breaks down into three sections. The first block contains metadata for
the overall page; the type of the page and the source table it is showing data from. The next section; the layout,
describes the visual parts on the page. The final section details the actions that are published on the page.
For more information about the Page and Page Extension objects, see Pages Overview.

IMPORTANT
Only pages with the Extensible Property set to true can be extended.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

IMPORTANT
The API page type should not be extended by creating a page extension object. Instead, create a new API by adding a
page object.

NOTE
Modifying actions in Cue groups on page extensions is not supported.

Snippet support
Typing the shortcut tpageext will create the basic layout for a page extension object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Views
Views in Dynamics 365 Business Central are used on list pages to define a different view of the data on a given
page. Views can be defined for Pages, Page Extensions, and Page Customization. For more information, see
Views.

Using keywords to place actions and controls


You can use the following keywords in the layout section to place and move fields and groups on the page
extension. Similarly, in the actions section, you use these keywords to place actions in the ribbon.

K EY W O RDS SY N TA X A P P L IES TO

addfirst addfirst(Anchor) Anchor : areas and groups

addlast addlast(Anchor) Anchor : areas and groups

addafter addafter(Anchor) Anchor : controls, actions, and groups

addbefore addbefore(Anchor) Anchor : controls, actions, and groups

movefirst movefirst(Anchor; Target1, Anchor : area, group


Target2) Target : list of actions or list of controls

movelast movelast(Anchor; Target1, Anchor : area, group


Target2) Target : list of actions or list of controls

moveafter moveafter(Anchor; Target1, Anchor : controls, actions, and groups


Target2) Target : list of actions or list of controls

movebefore movebefore(Anchor; Target1, Anchor : controls, actions, and groups


Target2) Target : list of actions or list of controls

modify modify(Target) Target : controls, actions, and groups

Example
To modify the existing fields and groups on a page, you use the modify keyword. See the code snippet below
for addlast , modify and action syntax. In the following example, the actions section creates a new group in
the ribbon and places it last in the Creation group.
pageextension 70000020 CustomerCardExtension extends "Customer Card"
{
layout
{
// Adding a new control field 'ShoeSize' in the group 'General'
addlast(General)
{
field("Shoe Size"; ShoeSize)
{
Caption = 'Shoe size';

trigger OnValidate();
begin
if (ShoeSize < 10) then
Error('Feet too small');
end;
}
}

// Modifying the caption of the field 'Address'


modify("Address 2")
{
Caption = 'New Address 2';
}

// Moving the two fields 'CreditLimit' and 'CalcCreditLimitLCYExpendedPct'


// to be the first ones in the 'Balance' group.
movefirst(Balance; CreditLimit, CalcCreditLimitLCYExpendedPct)
}
actions
{
// Adding a new action group 'MyNewActionGroup' in the 'Creation' area
addlast(Creation)
{
group(MyNewActionGroup)
{
action(MyNewAction)
{
Caption = 'My New Action';

trigger OnAction();
begin
Message('My message');
end;
}
}
}
}
}

tableextension 70000020 CustomerTableExtension extends Customer


{
fields
{
// Adding a new table field in the 'Customer' table
field(50100; ShoeSize; Integer) { }
}
}

Page extension examples


In the following example, we use a table extension to extend the Customer table with a new field named
ShoeSize of the datatype Integer. Then we create a page extension object that extends the Customer Card page
object by adding a field control ShoeSize to the General group on the page. The field control is added as the
last control in the group using the addlast method. The example also illustrates how to add a display-only
control to the page. In the actions area, you can see what the syntax looks like for actions that execute triggers
and actions that run objects.

tableextension 50115 RetailWinterSportsStore extends Customer


{
fields
{
field(50116;ShoeSize;Integer)
{
Caption = 'ShoeSize';

trigger OnValidate();
begin
if (rec.ShoeSize < 0) then
begin
message('Shoe size not valid: %1', rec.ShoeSize);
end;
end;
}
}

procedure HasShoeSize() : Boolean;


begin
exit(ShoeSize <> 0);
end;

trigger OnBeforeInsert();
begin
if not HasShoeSize then
ShoeSize := Random(42);
end;
}

pageextension 50110 CustomerCardExtension extends "Customer Card"


{
layout
{
addlast(General)
{
// control with underlying datasource
field("Shoe Size"; ShoeSize)
{
ApplicationArea = All;

trigger OnValidate();
begin
if (ShoeSize < 10) then
Error('Feet too small');
end;
}
// display-only control (without underlying datasource)
field(ShoesInStock; 10)
{
ApplicationArea = All;
Caption = 'Shoes in stock';

}
}

modify("Address 2")
{
Caption = 'New Address 2';
}
}

actions
{
{
addlast(Creation)
{
group(MyActionGroup)
{
Action(MyAction1)
{
ApplicationArea = All;
Caption = 'Hello!';

trigger OnAction();
begin
Message('My message');
end;
}

Action(MyAction2)
{
ApplicationArea = All;

// Run page to test how actions work


RunObject = page "Absence Registration";
}
}
}
}
}

You can reference Report and XMLPort objects and use these objects in the RunObject property, as well as,
declare variables of the types Repor t and XMLPor t and call AL methods on them. This page extension object
extends the Customer List page object by adding two actions; the first action calls the Customer - List report,
the second action calls the Expor t Contact XMLPort.

pageextension 50114 AddCustomerReport extends "Customer List"


{
actions
{
AddLast("&Customer")
{
action("Customer List Report")
{
trigger OnAction();
var
rep : Report "Customer - List";
begin
rep.Run;
end;
}

action("Export Contact List")


{
trigger OnAction();
var
xml : XmlPort "Export Contact";
begin
xml.Run;
end;
}
}
}
}

See Also
Page Object
Views
Page, Page Fields, and Page Extension Properties
Extending Pages Previously Based on the Date Virtual Table Developing Extensions
AL Development Environment
Page Customization Object
2/6/2023 • 2 minutes to read • Edit Online

The page customization object in Dynamics 365 Business Central allows you to add changes to the layout and
actions on page that are accessible for a profile. See Using keywords to place actions and controls for how to
place actions and controls on a page customization object.
The page customization object has more restrictions than the page extension object; when you define a new
page customization object, you cannot add variables, procedures, or triggers.

NOTE
A single page customization can be used with multiple profiles within the same extension. Page customizations only apply
to the RoleCenters they are specified for. In order to view or changes the RoleCenters in the client, go to My Settings >
Role Center .

NOTE
Extension objects can have a name with a maximum length of 30 characters.

NOTE
Modifying actions in Cue groups on page extensions is not supported.

NOTE
The property allowDebugging , which is a setting under resourceExposurePolicy does not apply to page
customizations. Page customizations defined in an extension with allowDebugging set to false can still be copied
using Designer. For more information, see Resource Exposure Policy Setting.

Snippet support
Typing the shortcut tpagecust will create the basic layout for a page customization object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Views
Views in Dynamics 365 Business Central are used on list pages to define a different view of the data on a given
page. Views can be defined for Pages, Page Extensions, and Page Customization. For more information, see
Views.
Page customization example
The following page customization example MyCustomization makes changes to Customer List . By using the
moveafter method, Blanket Orders is moved after the Orders action item. And the modify method is used to
hide the NewSalesBlanketOrder action item.

profile TheBoss
{
Description = 'The Boss';
RoleCenter = "Business Manager Role Center";
Customizations = MyCustomization;
Caption = 'Boss';
}

pagecustomization MyCustomization customizes "Customer List"


{
actions
{
moveafter(Orders; "Blanket Orders")

modify(NewSalesBlanketOrder)
{
Visible = false;
}

}
}

You can use the same page customization on another profile within the same extension package by referencing
its name from the profile definition, for example:

profile TheSalesman
{
ProfileDescription = 'The Boss';
RoleCenter = "Sales Manager Role Center";
Customizations = MyCustomization;
Caption = 'Salesman';
}

See Also
Developing Extensions
AL Development Environment
Page Object
Page Extension Object
Views
Page, Page Fields, and Page Extension Properties
Report Object
2/6/2023 • 4 minutes to read • Edit Online

Reports are used to print or display information from a database. You can use a report to structure and
summarize information, and to print documents, such as sales quotes and invoices.
Creating a report consists of two primary tasks; the first task is to create the underlying data model and the next
is to define the visual layout that displays the data. The report object defines the underlying data model and
specifies which database tables and fields to pull data from. When the report is run, that data is displayed in a
specified layout; the visual layout, which determines the content and format of a report when it's viewed and
printed.
For more information about defining database tables and fields, see Defining a Report Dataset. For more
information about the Report data type, see Report Data Type.
You build the layout of a report by arranging data items and columns, and specifying the general format, such as
text font and size. There are three types of report layouts; client report definition, also called RDL layouts, Word
layouts, and Excel layouts. RDL layouts are defined in Visual Studio Report Designer or Microsoft SQL Server
Reporting Services Report Builder. Word layouts are created using Word. Word layouts are based on a Word
document that includes a custom XML part representing the report dataset. Excel layouts are created in Excel
based on the report dataset, utilizing the Excel capabilities such as sliders, diagrams, charts, pivot tables, and
PowerQuery. One report can contain multiple report layout definitions. For more information, see Defining
Multiple Report Layouts.
If you want to modify an existing report, for example, add new columns, add to the request page, or add a new
layout, you can create a report extension instead. For more information, see Report Extension Object.

TIP
It is possible to use a query object as the data source for a report. This can in many cases improve the performance of
data retrieval when running the report.

Snippet support
Typing the shortcut treport will create the basic layout for a report object when using the AL Language
extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Report example
The following example is a report that prints the list of customers. The report object defines a dataset of
columns from the Customer table. This example defines a report that uses an RDL report layout. For more
information about creating an RDL report layout, see Creating an RDL Layout Report. For more information on
creating a report that uses Word Layout, see Creating a Word Layout Report. For information about creating an
Excel layout, see Creating an Excel Layout Report.
report 50103 "Customer List"
{
CaptionML=ENU='Customer List';
DefaultLayout = RDLC; // if Word use WordLayout property
RDLCLayout = 'MyRDLReport.rdl';

dataset
{
dataitem(Customer;Customer)
{
RequestFilterFields="No.","Search Name","Customer Posting Group";
column(CompanyName;CompanyName)
{
}
column(CurrReport_PageNo;Customer."no.")
{
}
column(Customer_TableCaption_CustFilter;TableCaption + ': ' + CustFilter)
{
}
column(CustFilter;CustFilter)
{
}
column(Customer_No;"No.")
{
}
column(Customer_Customer_Posting_Group;"Customer Posting Group")
{
}
column(Customer_Customer_Disc_Group;"Customer Disc. Group")
{
}
column(Customer_Invoice_Disc_Code;"Invoice Disc. Code")
{
}
column(Customer_Customer_Price_Group;"Customer Price Group")
{
}
column(Customer_Fin_Charge_Terms_Code;"Fin. Charge Terms Code")
{
}
column(Customer_Payment_Terms_Code;"Payment Terms Code")
{
}
column(Customer_Salesperson_Code;"Salesperson Code")
{
}
column(Customer_Currency_Code;"Currency Code")
{
}
column(Customer_Credit_Limit_LCY;"Credit Limit (LCY)")
{
DecimalPlaces=0:0;
}
column(Customer_Balance_LCY;"Balance (LCY)")
{
}
column(CustAddr_1;CustAddr[1])
{
}
column(CustAddr_2;CustAddr[2])
{
}
column(CustAddr_3;CustAddr[3])
{
}
column(CustAddr_4;CustAddr[4])
{
}
}
column(CustAddr_5;CustAddr[5])
{
}
column(Customer_Contact;Contact)
{
}
column(Customer_Phone_No;"Phone No.")
{
}
column(CustAddr_6;CustAddr[6])
{
}
column(CustAddr_7;CustAddr[7])
{
}
column(Customer_ListCaption;Customer_ListCaptionLbl)
{
}
column(CurrReport_PageNoCaption;CurrReport_PageNoCaptionLbl)
{
}
column(Customer_NoCaption;FieldCaption("No."))
{
}
column(Customer_Customer_Posting_GroupCaption;Customer_Customer_Posting_GroupCaptionLbl)
{
}
column(Customer_Customer_Disc_GroupCaption;Customer_Customer_Disc_GroupCaptionLbl)
{
}
column(Customer_Invoice_Disc_CodeCaption;Customer_Invoice_Disc_CodeCaptionLbl)
{
}
column(Customer_Customer_Price_GroupCaption;Customer_Customer_Price_GroupCaptionLbl)
{
}
column(Customer_Fin_Charge_Terms_CodeCaption;FieldCaption("Fin. Charge Terms Code"))
{
}
column(Customer_Payment_Terms_CodeCaption;Customer_Payment_Terms_CodeCaptionLbl)
{
}
column(Customer_Salesperson_CodeCaption;FieldCaption("Salesperson Code"))
{
}
column(Customer_Currency_CodeCaption;Customer_Currency_CodeCaptionLbl)
{
}
column(Customer_Credit_Limit_LCYCaption;FieldCaption("Credit Limit (LCY)"))
{
}
column(Customer_Balance_LCYCaption;FieldCaption("Balance (LCY)"))
{
}
column(Customer_ContactCaption;FieldCaption(Contact))
{
}
column(Customer_Phone_NoCaption;FieldCaption("Phone No."))
{
}
column(Total_LCY_Caption;Total_LCY_CaptionLbl)
{
}

trigger OnAfterGetRecord();
begin
CalcFields("Balance (LCY)");
FormatAddr.FormatAddr(
CustAddr,Name,"Name 2",'',Address,"Address 2",
CustAddr,Name,"Name 2",'',Address,"Address 2",
City,"Post Code",County,"Country/Region Code");
end;

}
}

requestpage
{
SaveValues=true;
ContextSensitiveHelpPage = 'my-feature';
layout
{
}

actions
{
}
}

labels
{
LabelName = 'LabelText', Comment = 'Foo', MaxLength = 999, Locked = true;
}

trigger OnPreReport();
var
CaptionManagement : Codeunit 42;
begin
CustFilter := CaptionManagement.GetRecordFiltersWithCaptions(Customer);
end;

var
FormatAddr : Codeunit 365;
CustFilter : Text;
CustAddr : ARRAY [8] OF Text[50];
Customer_ListCaptionLbl : Label 'Customer - List';
CurrReport_PageNoCaptionLbl : Label 'Page';
Customer_Customer_Posting_GroupCaptionLbl : Label 'Customer Posting Group';
Customer_Customer_Disc_GroupCaptionLbl : Label 'Cust./Item Disc. Gr.';
Customer_Invoice_Disc_CodeCaptionLbl : Label 'Invoice Disc. Code';
Customer_Customer_Price_GroupCaptionLbl : Label 'Price Group Code';
Customer_Payment_Terms_CodeCaptionLbl : Label 'Payment Terms Code';
Customer_Currency_CodeCaptionLbl : Label 'Currency Code';
Total_LCY_CaptionLbl : Label 'Total (LCY)';
}

TIP
From the Business Central client, you can export report results as raw data to a Microsoft Excel file. The file contains all
columns of the dataset, but without the layout applied. Use the file to help validate that the report returns the expected
data, and to ensure that the report layout controls match the dataset value types. To export a report, run the report and
select the Send to > Microsoft Excel Document (data only) on the request page. For more information, see
Working with Reports - Send to Excel.

Schedule reports
It's possible to schedule a report to run at your desired date and time by using AllowScheduling property. By
setting the property to true, you'll get the Schedule action button to set the date and time for your report. To
learn more about scheduling a report, see AllowScheduling Property and Schedule a report.
See also
Report Extension Object
Request Pages
Report Properties
Creating an RDL Layout Report
Creating a Word Layout Report
Adding Help Links from Pages, Reports, and XMLports
Page Extension Object
Page Properties
Developing Extensions
AL Development Environment
Profile Object
2/6/2023 • 2 minutes to read • Edit Online

The profile object in Dynamics 365 Business Central allows you to build an individual experience for each user
profile. The Profile object performs a validation to check whether the specified role center page exists, and page
customization objects exists, when you define a new profile object. On a page customization you can add
changes to the page layout, and actions; but you cannot add variables, procedures, or triggers.

NOTE
Page customizations only apply to the RoleCenter they are specified for. In order to see them, in Dynamics 365 Business
Central under My Settings , Role Center change to the specific RoleCenter that a page customization is defined for.

NOTE
Extension objects can have a name with a maximum length of 30 characters.

NOTE
The property allowDebugging , which is a setting under resourceExposurePolicy does not apply to page
customizations. Page customizations defined in an extension with allowDebugging set to false can still be copied
using Designer. For more information, see Resource Exposure Policy Setting.

Snippet support
Typing the shortcut tprofile will create the basic layout for a profile object when using the AL Language
extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Profile example
The following profile object example creates a profile for the MyRoleCenter Role Center, which is available in the
Role Explorer in the UI and available to end-users. The profile also depends on the customization
MyCustomization and modifies the layout of the Customer List to make the Name field invisible using the
modify method. For more information, see Profile Properties.
profile MyProfile
{
Description = 'Some internal comment that only the Dev can see';
Caption = 'My User-friendly Name';
ProfileDescription = 'A detailed description of who is this profile for, why/how to use it (etc)';
RoleCenter = MyRoleCenter;
Enabled = true;
Promoted = true;
Customizations = MyCustomization;
}

pagecustomization MyCustomization customizes "Customer List"


{
layout
{
modify(Name)
{
Visible = false;
}
}
}

See Also
AL Development Environment
Developing Extensions
Pages Overview
Page Customization Object
Codeunit Object
2/6/2023 • 2 minutes to read • Edit Online

A codeunit is a container for AL code that you can use in many application objects. You typically implement
business logic in codeunits and call the codeunit from the object that needs to perform that specific logic.

Snippet support
Typing the shortcut tcodeunit will create the basic layout for a codeunit object when using the AL Language
extension in Visual Studio Code.

Codeunit example
This codeunit example checks whether a given customer has registered a shoe size. If not, the customer is
assigned a shoe size of 42.
The codeunit can be used both as a direct call to codeunit.run(customer) or as a call to the procedure inside the
codeunit createcustomer.CheckSize(customer) .

codeunit 50113 CreateCustomer


{
TableNo = Customer;
trigger OnRun();
begin
CheckSize(Rec);
end;
procedure CheckSize(var Cust : Record Customer)
begin
if not Cust.HasShoeSize() then
Cust.ShoeSize := 42;
end;
}

See Also
Developing Extensions
Table Extension Object
Page Extension Object
AL Development Environment
XML Comments in Code
Query Object
2/6/2023 • 4 minutes to read • Edit Online

Business Central query objects enable you to retrieve records from one or more tables and then combine the
data into rows and columns in a single dataset. Query objects can also perform calculations on data, such
finding the sum or average of all values in a column of the dataset.
There are two types of query objects: normal and API. This article describes normal query objects, which can be
used to display data in the user interface. API query objects are used to generate web service endpoints and
cannot be displayed in the user interface. For information about creating a query of the type API, see API Query
Type.

Creating a query object


A query object is comprised mainly of two different types of elements: dataitems and columns. A dataitem
specifies the table to retrieve records from. A column specifies a field of the table to include in the resulting
dataset of a query. The basic steps to create a query object are as follows:
1. Add the query keyword, followed by the elements control.
2. Build the dataset by adding dataitem controls and column controls within the elements control.
The hierarchy of the dataitem and column controls is important because it will determine the sequence
in which data items are linked, which in turn will control the results. Working from top-to-bottom, you
start by adding the dataitem control for first table that you want in the dataset, then add column
controls for each table field that you want to include in the dataset. For the next table, you add another
dataitem control that is embedded within the first dataitem control, then add column controls as
needed. You continue this pattern for additional tables and fields.
3. When you have specified the dataitem and column elements, create links and joins between the
dataitem elements.

Dataitem links and joins determine which records to include in the dataset based on the values of a
common field between dataitems. You set a link between one or more fields of the dataitem tables with
the DataItemLink Property and you define the type of the link using the SQLJoinType Property. Both
properties must be set on the lower dataitem of the query object. For more information, see Linking and
Joining Data Items.
The following shows the basic structure of a query object.
query ID Name
{

elements
{
dataitem(DataItem1; Table1)
{
column(Column1; Field1)
{
}
column(Column2; Field2)
{
}
dataitem(DataItem2; Table2)
{
// Sets a link between FieldY of Table2 and FieldX of Table1.
DataItemLink = FieldY = DataItem1.FieldX;
//The dataset contains records from Table1 and Table2 where a match is found between FieldY
and FieldX.
SqlJoinType = InnerJoin;

column(Column1; Field1)
{
}
dataitem(DataItem3; Table3)
{
DataItemLink = FieldZ = DataItem2.FieldY;
SqlJoinType = InnerJoin;
column(Column1; Field1)
{
}
}
}
}
}
}

NOTE
Extension objects can have a name with a maximum length of 30 characters.

Snippet support
Typing the shortcut tquery will create the basic layout for a Query object when using the AL Language
extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Query example
The following example shows a query that displays a list of customers with sales and profit figures. The query
primarily retrieves fields from the Customer table, but also displays fields from the Salesperson Purchaser
and Countr y Region tables.
The query also uses the DataItemLink property to create a link between the Customer table, Salesperson
Code field and the Salesperson Purchaser table, Code fields and a link between the Customer table,
Countr y/Region Code field and the Countr y/Region table, Code field.

query 50102 "Top Customer Overview"


{
QueryType = Normal;
Caption = 'Top Customer Overview';

DataAccessIntent = ReadOnly; // use this to read data from the secondary database replica to speed up
performance

elements
{
dataitem(Customer; Customer)
{
column(Name; Name)
{
}
column(No; "No.")
{
}
column(Sales_LCY; "Sales (LCY)")
{
}
column(Profit_LCY; "Profit (LCY)")
{
}
column(Country_Region_Code; "Country/Region Code")
{
}
column(City; City)
{
}
column(Global_Dimension_1_Code; "Global Dimension 1 Code")
{
}
column(Global_Dimension_2_Code; "Global Dimension 2 Code")
{
}
column(Salesperson_Code; "Salesperson Code")
{
}
dataitem(Salesperson_Purchaser; "Salesperson/Purchaser")
{
DataItemLink = Code = Customer."Salesperson Code";
column(SalesPersonName; Name)
{
}
dataitem(Country_Region; "Country/Region")
{
DataItemLink = Code = Customer."Country/Region Code";
column(CountryRegionName; Name)
{
}
}
}
}
}
}
IMPORTANT
You cannot run a query that gets data from both the application database and the business data database. This also
applies to single-tenant deployments so that you do not have to rewrite queries if you decide to export the application.
For a description of which tables are considered part of the application database, see Separating Application Data from
Business Data.

See Also
Linking and Joining Data Items
Aggregating Data in Query Objects
Query Objects and Performance
Query Properties
Query DataAccessIntent
Developing Extensions
AL Development Environment
API Query Type
XMLport Object
2/6/2023 • 2 minutes to read • Edit Online

XMLports are used to export and import data between an external source and Dynamics 365 Business Central.
Sharing data between different computer systems is seamless when it is shared in an XML format. Working with
XML files can be tedious so the details of how the XML file is handled are encapsulated in XMLports.
To use an XMLport to import or export data, you first create an XMLport object. Once created, you can run the
XMLport from a page or codeunit object.
You can design XMLports to include a request page, which is a dialog box that enables the user to set a filter on
the data, sort the data, or choose whether to export or import the data. For more information about request
pages, see Request Pages.

XMLport example
The following example shows a page extension of the Permission Sets page that adds an action to the
specified page calling the XMLport Expor tPermissionSet . The XMLport exports the permission set data to an
XML file.

pageextension 50111 PermissionSetExporter extends "Permission Sets"


{
actions
{
addafter(Permissions)
{
action(ExportPermissionSet)
{
Promoted = true;
PromotedCategory = New;
trigger OnAction();
begin
Xmlport.Run(50112, false, false);
end;
}
}
}
}

xmlport 50112 ExportPermissionSet


{
Format = xml;

schema
{
textelement(PermissionSets)
{
tableElement(PSet; "Aggregate Permission Set")
{
SourceTableView = WHERE ("App Name" = FILTER (<> ''));
XmlName = 'PermissionSet';
fieldattribute(RoleID; pset."Role ID") { }
fieldattribute(RoleName; pset.Name) { }
tableelement(P; "Tenant Permission")
{
XmlName = 'Permission';
LinkTable = pset;
LinkFields = "Role ID" = FIELD ("Role ID");
textelement(ObjectType)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Object Type";
ObjectType := format(int);
end;
}
textelement(ObjectID)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Object ID";
ObjectID := format(int);
end;
}
textelement(ReadPermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Read Permission";
ReadPermission := format(int);
end;
}
textelement(InsertPermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Insert Permission";
InsertPermission := format(int);
end;
}
textelement(ModifyPermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Modify Permission";
ModifyPermission := format(int);
end;
}
textelement(DeletePermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Delete Permission";
DeletePermission := format(int);
end;
}
textelement(ExecutePermission)
{
trigger onbeforePassvariable();
var
int: Integer;
begin
int := p."Execute Permission";
ExecutePermission := format(int);
end;
end;
}
textelement(SecurityFilter)
{
trigger onbeforePassvariable();
begin
SecurityFilter := format(p."Security Filter");
end;
}
}
}
}
}
}

See Also
Developing Extensions
AL Development Environment
XMLport Overview
Using Namespaces with XMLports
Page Extension Object
Report Object
Control Add-In Object
2/6/2023 • 4 minutes to read • Edit Online

The control add-in object allows you to add custom functionality to Dynamics 365 Business Central. A control
add-in is a custom control, or visual element, for displaying and modifying data within an iframe or a page. For
example, a control add-in can display the content of a webpage, visualize data as a chart or on a map, or host a
custom web application. Control add-ins can exchange data with the Dynamics 365 server on various data types
and respond to user interaction to raise events that execute additional AL code.

Control add-in properties


In the control add-in definition, you must set the Scripts property to include scripts in the control add-in. The
scripts could be local files in the package or references to external files using the HTTP or the HTTPS protocol.
With the StartupScript property, you can call a special script that runs when the page you've implemented the
control add-in on, is loaded. These settings initialize the control add-in. With the Images and StyleSheet
properties, you can specify additional styling to the control add-in. For more information about some of the
control add-in properties, see:
Images
Scripts
StartupScript
StyleSheets
RecreateScript
RefreshScript

Sizing of the control add-in


Control add-ins can either have fixed dimensions or dynamically adapt to the available space on the screen. By
controlling the sizing of an add-in, you ensure the add-in and the surrounding content on the page remain
optimal on smaller display targets such as the phone or when users resize the browser. The following properties
are available for you to specify how the sizing of the control add-in should behave.
HorizontalShrink
HorizontalStretch
MinimumHeight
MinimumWidth
MaximumHeight
MaximumWidth
RequestedHeight
RequestedWidth
VerticalShrink
VerticalStretch

Control add-in considerations and limitations


Designing control add-ins that provide the best possible experience can require some additional planning,
design, and implementation. The following considerations and limitations will help you design add-ins that look
and feel seamlessly integrated with both Dynamics 365 Business Central online and on-premises.
Respond to touch events so that mobile users or users on devices supporting touch input can also use
the add-in.
Design content that is responsive and can flow, resize, or reorganize naturally based on the available
space.
Consider the accessibility needs of users, for example by implementing keyboard access and support for
screen readers.
Use the Style guidelines to apply a choice of colors, typefaces, and font sizes that match that of Dynamics
365 Business Central. For more information, see Control Add-in Style Guide.
Provide language translation and other localizations that match the current user language in Dynamics
365 Business Central.
In extensions for Business Central online, don't reference font files in stylesheets, because the fonts won't
display in client. Instead, do one of the following:
Reference the font files from some other source such as a public or private CDN.
Base64 encode the fonts and include the encoded fonts in the CSS file.
For more information about writing efficient code for contron add-ins, see Control Add-In Best Practices.

Control add-in syntax example


The following control add-in syntax shows how to implement small customizations of the layout and
functionality of a page.

// The controladdin type declares the new add-in.


controladdin SampleAddIn
{
// The Scripts property can reference both external and local scripts.
Scripts = 'https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-debug.js',
'main.js';
// The StartupScript is a special script that the web client calls once the page is loaded.
StartupScript = 'startup.js';

// Specifies the StyleSheets that are included in the control add-in.


StyleSheets = 'skin.css';

// Specifies the Images that are included in the control add-in.


Images = 'image.png';

// The procedure declarations specify what JavaScript methods could be called from AL.
// In main.js code, there should be a global function CallJavaScript(i,s,d,c)
{Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('CallBack', [i, s, d, c]);}
procedure CallJavaScript(i: integer; s: text; d: decimal; c: char);

// The event declarations specify what callbacks could be raised from JavaScript by using the webclient
API:
// Microsoft.Dynamics.NAV.InvokeExtensibilityMethod('CallBack', [42, 'some text', 5.8, 'c'])
event Callback(i: integer; s: text; d: decimal; c: char);
}

The controladdin object is then invoked as a usercontrol on a page called PageWithAddIn .


page 50130 PageWithAddIn
{
layout
{
area(Content)
{
// The control add-in can be placed on the page using usercontrol keyword.
usercontrol(ControlName; SampleAddIn)
{

ApplicationArea = All;

// The control add-in events can be handled by defining a trigger with a corresponding
name.
trigger Callback(i: integer; s: text; d: decimal; c: char)
begin
Message('Got from js: %1, %2, %3, %4', i, s, d, c);
end;
}
}
}

actions
{
area(Creation)
{
action(CallJavaScript)
{
ApplicationArea = All;

trigger OnAction();
begin

// The control add-in methods can be invoked via a reference to the usercontrol.
CurrPage.ControlName.CallJavaScript(5, 'text', 6.3, 'c');
end;
}
}
}
}

Loading static resources using AJAX requests


You can design a control add-in to load static resources from the add-in package by using AJAX requests. For
example, the control add-in could load HTML content and inject it into add-in's HTML structure. In this case, you
must use the withCrendentials property set to true in the AJAX request. Otherwise, the request won't contain
the necessary context and important cookies required by the Business Central service, and it may fail in
production. This concept is illustrated in the following examples.
Wrong:

$.get(url).done(function(response) { } );

Correct:
$.ajax({
url: url,
xhrFields: {
withCredentials: true
}
)).done(function(data) {
$("#controlAddIn").text(data);
});

See Also
AL Development Environment
Developing Extensions
Asynchronous Considerations for Control Add-ins
Control Add-In Best Practices
InvokeExtensibility Method
GetImageResource Method
GetEnvironment Method
Pages Overview
Page Extension Object
Page Customization Object
Entitlement Object
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

The entitlement object in Business Central describes which objects in Business Central a customer is entitled to
use according to the license that they purchased or the role that they have in AAD.
An entitlement consists of a number of PermissionSet Objects put together to constitute a set of meaningful
permissions for a user. An entitlement can only include permission set objects which reference the objects that
are included within the same app. This is to ensure that the entitlements included with one app cannot alter or
redefine the entitlements included with another app.
Entitlements can only be used with the online version of Business Central.

NOTE
In the current version of Business Central entitlements can only be included with Microsoft apps (enforced by the
AppSource cop rules and the technical validation checks that we run for the apps submitted to AppSource). These objects
will become available for the ISV apps when we introduce ability to monetize AppSource apps in one of our future
releases.

Snippet support
Typing the shortcut tentitlement will create the basic layout for an entitlement object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Entitlement examples
This example illustrates a simple entitlement object with the Type property set to Role , which means that the is
entitlement is associated with an AAD role. When Type is set to Role , the RoleType property is used to
distinguish between local and delegated assignments of the role, in this case it is Delegated . The
ObjectEntitlements property defines the list of permissions that the entitlement includes.

entitlement BC_Role_Delegated
{
Type = Role;
RoleType = Delegated;
Id = '1a2aaaaa-3aa4-5aa6-789a-a1234567aaaa';
ObjectEntitlements =
”D365 BUS PREMIUM - BaseApp”;
}

An example of an entitlement where Type is PerUserServicePlan :


entitlement BC_PerUserServicePlan
{
Type = PerUserServicePlan;
Id = '1a2aaaaa-3aa4-5aa6-789a-a1234567aaaa';

ObjectEntitlements = "D365 BASIC";

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Extension Object
Permission Set Object
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

The permission set object in Business Central describes permissions on objects. Permission sets are building
blocks used to compose assignable permission sets and entitlements. Assignable permission sets are
permissions that an admin can assign to users in Business Central, using the Permission Sets page. An
entitlement is a collection of permission sets that constitute a set of meaningful permissions for a user.
Some permission sets can be non-assignable, meaning that they aren't discoverable and assignable in the UI in
Business Central, instead they can be used as building blocks to compose functional assignable permission sets.
For information about which permissions can be assigned to objects, see Permissions on Database Objects.

Designing with cautiousness


If a permission set is extended through AL, the extension will make additive changes to the permission set. This
behavior means an extension can provide elevated privileges to an otherwise limited set of permissions.
Building permission sets that can be extended must be done carefully with this behavior in mind.

Snippet support
Typing the shortcut tpermissionset will create the basic layout for a permission set object when using the AL
Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Generate permission set for an object


APPLIES TO: Business Central 2022 release wave 2 and later

When adding new AL objects, it's easy to forget to update the permissions. With the
al.generatePermissionSetForExtensionObjects command, you can generate or update a permission file for the
active project in Visual Studio Code. Choose to create a new permission file or select an existing file to make
updates to. For more information, see AL Language Extension Configuration.

Permission set example


The following example illustrates a permission set Sales Person with permissions given to data in tables, each
with different level of access. The Assignable property is set to true , which allows the permission set to be
assigned to a user. The Permissions property is set to the list of objects to give permissions to. The RIMD access
assigned to data in the Customer table provides full access, whereas, for example, access is limited for data in
the Currency table only allowing full read and modify permission.
NOTE
The name of the permissionset object is limited to 20 characters when the Assignable property is set to true .
Otherwise, it's limited to 30 characters. Exceeding the limit will throw the diagnostic Compiler Error AL0305.

permissionset 50134 "Sales Person"


{
Assignable = true;
Caption = 'Sales Person';

Permissions =
tabledata Customer = RIMD,
tabledata "Payment Terms" = RMD,
tabledata Currency = RM,
tabledata "Sales Header" = RIM,
tabledata "Sales Line" = RIMD;
}

The following example of a permission set illustrates assigned permissions to run codeunits. With the
IncludedPermissionSets property, we specify that the permission set Sales Person is also included in
MyPermissionSet .

permissionset50135MyPermissionSet
{
Assignable = true;
Caption = 'My PermissionSet';
IncludedPermissionSets= "Sales Person";

Permissions=
tabledataVendor=RIm,
codeunit SomeCode =x,
codeunit AccSchedManagement=X;
}

You can also use the ExludedPermissionSets property to exclude permissions defined in other permission sets.
To learn more, see Composing Permission Sets From Other Permission Sets.

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Extension Object
Permissions on Database Objects
Assignable Property
IncludedPermissionSets
Permissions Property
Permission Set Extension Object
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2021 release wave 1 (v18.0) and later

The permission set extension object in Business Central adds permissions to an existing permission set defined
in AL. A permission set extension object cannot remove permissions from an existing permission set, it can only
add permissions. If you, for example, add an extension to Business Central, you can use permission set extension
objects to grant permissions to the objects in your extension. This means that the admin of Business Central
does not have to assign additional permission sets to the users, because that automatically happens when the
extension is installed, and the permissions go away if the extension is uninstalled.
For information about which permissions can be assigned to objects, see Permissions on Database Objects.

Designing with cautiousness


If a permission set is extended through AL, that extension will make additive changes to the permission set. This
means that an extension can provide elevated privileges to an otherwise limited set of permissions. Building
permission sets that can be extended must be done carefully with this in mind.

Snippet support
Typing the shortcut tpermissionsetextension will create the basic layout for a permission set extension object
when using the AL Language extension in Visual Studio Code.

TIP
Use Ctrl+Space to trigger IntelliSense and get assistance on code completion, parameter info, quick info, and member
lists.

Permission set example


The following permission set extension example extends the Sales Person permission set by adding direct
insert and delete permissions to the Currency table data.

permissionsetextension 50140 "Extended Sales Doc" extends "Sales Person"


{
Permissions = tabledata Currency = ID;
}

See Also
Developing Extensions
AL Development Environment
Entitlements and Permission Set Overview
Permission Set Object
Permissions on Database Objects
Assignable Property
Permissions Property
AL Platform Overview
2/6/2023 • 2 minutes to read • Edit Online

This section introduces the different parts of the AL platform that are available for extension developers who
want to extend the business functionality of Business Central.

Platform capabilities
Business Central comes with a rich platform of system modules and capabilities that you can leverage in your
extensions. Getting familiar with the modules in the Business Central system application might save you a lot of
time as it contains implementations of many generic tasks you might need. For more information, see Overview
of the System Application.
Learning how to start background sessions using the task scheduler and job queues can help you offload work
from UI sessions. For more information, see Task Scheduler.
Instrumenting your extension using feature telemetry and custom telemetry can help you monitor the extension
after it has been deployed to production. For more information, see Creating Custom Telemetry Events.

See Also
Overview of the System Application
Task Scheduler
Job Queue
Using Azure Key Vaults for Secrets
Creating Custom Telemetry Events
Add Feature Usage Telemetry
Creating a Printer Extension
Getting started with Microsoft .NET Interoperability from AL (on-premises only)
Overview of the System Application
2/6/2023 • 4 minutes to read • Edit Online

The System Application contains modules that interact with the Dynamics 365 Business Central platform and
online ecosystem to support the business logic in the Base Application. If you are developing extensions or add-
ons for Dynamics 365 Business Central, you will probably need to use one or more of the objects in the
modules.
This topic provides an overview of the modules in the System Application. For more details about each module,
and to get a look at the code, choose the ReadMe link for the module to visit our ALAppExtensions repository
on GitHub.

NOTE
The modules in the System Application represent a significant change in what's happening under the hood in Dynamics
365 Business Central. We are aware that the changes we have made will introduce breaking changes, so we have made a
list of those that we know about, which includes suggestions for solutions. To view the breaking changes list, see Breaking
Changes.

We will continue to enhance the System Application in future releases. If you find something you think we should add,
visit our Dynamics 365 Application Ideas page. If you want us to improve something, go to the ALAppExtensions
repository and submit a pull request for it.

Overview of the Modules in the System Application


The list of modules is growing continuously. The following table lists and describes the modules that are
available now.

M O DUL E DESC RIP T IO N L IN K TO REA DM E

Auto Format Formats the appearance decimal data ReadMe


types.

Azure AD Graph Interface for the Azure AD Graph API. ReadMe

Note
Azure Active Directory Graph is being
retired, and we recommend that you
start using Microsoft Graph instead. To
avoid causing issues with apps that
use the Azure AD Graph module in
Business Central, we haven't changed
its name or the names of the objects it
contains. For more information about
the Azure Active Directory Graph
retirement, see Migrate Azure AD
Graph apps to Microsoft Graph.

Azure AD Licensing Access information about the ReadMe


subscribed SKUs and the
corresponding service plans.
M O DUL E DESC RIP T IO N L IN K TO REA DM E

Azure AD Plan Provides methods for retrieving and ReadMe


managing user plans in Azure Active
Directory.

Azure AD Tenant Retrieves information about the Azure ReadMe


Active Directory tenant.

Azure AD User Management Provides functionality for managing ReadMe


Azure Active Directory users.

Azure AD User Retrieves and updates a user from the ReadMe


Azure AD Graph API.

Azure Functions Provides functionality for connecting ReadMe


to Azure Functions and gathering data
about the success of calls from
Business Central to Azure Functions.

Azure Key Vault Stores Azure Key Vault secrets for ReadMe
deployments.

BLOB Storage Stores and manages data in a binary ReadMe


format.

Base64 Convert Converts text and from base 64. ReadMe

Barcode Exposes functionality to encode ReadMe


barcodes for using on, for example,
reports.

Caption Class Defines how the CaptionClass ReadMe


property displays captions.

Client Type Management Allows testing of code that relies on ReadMe


different types of clients.

Confirm Management Determines whether a confirm dialog ReadMe


displays when logic is run.

Cryptography Management Contains the capabilities for encryption ReadMe


and hashing.

Cues and KPIs Provides setup pages and interface ReadMe


methods to manage cues.

Data Classification Handles data classification for objects ReadMe


that might contain sensitive
information.

Data Compression Compresses and uncompresses data in ReadMe


a binary format.

Date-Time Dialog Provides helper functions for entering ReadMe


date-time values.
M O DUL E DESC RIP T IO N L IN K TO REA DM E

Default Role Center Supports the default RoleCenter ReadMe


selection.

Document Sharing Enable document sharing flows ReadMe


through a valid document service, like
OneDrive for Business

DotNet Aliases Defines aliases for .NET classes. ReadMe

Environment Information Contains helper methods for getting ReadMe


information about the tenant and
general settings.

Extension Management Provides the tools needed to manage ReadMe


an extension.

Field Selection Looks up fields. ReadMe

Filter Tokens Provides helper functions to manage ReadMe


filter texts.

Headlines Helps with constructing the text for ReadMe


headlines.

Language Changes the language for Windows ReadMe


and applications.

Math Provides constants and static methods ReadMe


for trigonometric, logarithmic, and
other common mathematical
functions.

Object Selection Look up page for all of the application ReadMe


objects, including objects from installed
extensions.

Page Summary Provider Contains functionality for providing ReadMe


summary data for a given page in
Microsoft Teams.

Password Sets and verifies passwords. ReadMe

Printer Management Contains functionality that enables a ReadMe


user to manage printers.

Record Link Management Provides helper functions for ReadMe


RecordLinks.

Recurrence Schedule Calculates when the next event will ReadMe


occur.

Satisfaction Survey Shows a satisfaction survey. ReadMe


M O DUL E DESC RIP T IO N L IN K TO REA DM E

Secrets Contains secret providers for reading ReadMe


secrets from the key vault that is
specified by an extension or from other
secret providers.

Server Settings Exposes methods that get settings ReadMe


from the server configuration file.

System Initialization Runs non-business logic on user log- ReadMe


ins.

Tenant License State Retrieves the current state of the ReadMe


tenant license.

Translation Gets and stores language translations. ReadMe

Upgrade Tags Provides functionality for ensuring that ReadMe


the upgrade code is run only one time.

User Log-In Times Keeps track of when users sign in. ReadMe

User Permissions Exposes functionality to check and ReadMe


alter User Permission sets.

User Selection Looks up and selects registered users. ReadMe

Video Looks up and plays videos. ReadMe

Web Service Management Provides the tools needed to manage ReadMe


web services.

See Also
ALAppExtensions
Module Architecture
2/6/2023 • 5 minutes to read • Edit Online

Though the internal architecture of modules can, and most likely will, differ, there are rules that ensure
consistency and reliability in the architecture of application modules. To reduce coupling and increase
consistency, every module is a separate entity that has a publicly accessible facade, while the internal
implementation is not public, as shown in the following image:

The following sections describe the design principles for modules.

One Module, One Project


Modules are independent projects and have their own app.json files. For details about the contents of the
app.json file, see Project Setup.

Packaging and Layering


Modules can belong to a specific package, or functional layer. A module becomes part of a layer when it’s added
to the folder structure of the layer’s package. A module can belong to several packages because the module is a
package of its own, and can be bundled into larger functional layering packages.

Dependencies
Dependencies to other modules can only be taken to modules in the same functional layer or to lower layers.
For example, a module in the Core Application can only take dependencies to modules in the Core Application
or System Application, but never to extensions.

Target Environment
Every module must initially target the most restrictive environment, which is the cloud environment. If unsafe
operations are required, those should result in a System Application module where the unsafe operations are
wrapped with safe APIs. That is done by setting the Target to OnPrem . Modules in layers above the System
Application must have Target set to Cloud in the app.json file.
Object Accessibility
Only facade codeunits, pages, and tables required in the public API of the module can be accessible. Internal
implementation details must be marked as such by setting the access modifier to Internal, i.e. entities can be
accessed within the module but cannot be called from outside the module.

Facade Codeunits
Every module must have a facade that meets the following rules:
Access must be Public . It should be set explicitly to emphasize that this is a facade or an API-like codeunit
that exposes the core functionality in the module.
All integration and business event publishers must be in the facade as internal functions. This prevents them
from being invoked outside the module.
Event publishers should be marked as internal. Exceptions must be documented.
All external methods go in the facade.
Facades cannot contain logic or local functions.
Because the facade is the codeunit that other modules reference, it should have a short, meaningful name.
Internal implementation codeunits can be suffixed with “Impl,” for example, because they are not referenced
outside the module.

Business Logic
Implementation codeunits contain the business logic. Pages and tables can contain code, but should do so only
when it's absolutely required.

Extensibility
Extensibility must be thought into the internal implementation of every module. If a module should not be
extensible, the Extensibility property on tables, pages, and enums must be set to False to prevent those
objects from being extended.
Functions and fields in extensible tables and pages must have an access modifier, as described in the following
table.

A C C ESS DESC RIP T IO N

Local Accessed only by code in the same table or table extension


where the function or field is defined.

Internal Accessed only by code in the same module, but not from
another module.

Protected Accessed only by code in the same table or table/page


extensions of that table.

Public Accessed by any other code in the same module and in


other modules that reference it.

Documentation
Every publicly accessible object must be documented. For more information, see Documentation.
Tests
Every module’s public API must be tested according to Microsoft standards. For more information, see Testing.

Single Instance
Use single instance only when it’s required, or if the module is expected to be called frequently.

.NET
If a .NET type is an integral part of the module and is not referenced elsewhere, the alias for that type must be
defined in the module. If the .NET type is used in different modules, then the alias for it must be defined in the
DotNet Aliases module.

Project Setup
Every module begins with a project setup that includes the following:
Module Name : If the module represents an entity, name the module after the entity. If the module does not
represent an entity, give it a name that describes what it does. Module names can be singular or plural,
depending on whether they handle one or more entities or tasks.
Location : Determine which layer the module belongs to, and create a subfolder in a folder in that layer. For
example, Modules\System\My Module).
Source Code : Add the source code of the module in a src subfolder. For example, Modules\System\My
Module\src).

Testing
Every module must be tested through a separate test module. Only public functions that are exposed through
the facade, or other public objects such as pages, tables, xmlports, and queries, are tested by the test module.

The test module should have the same name as the module it tests, but be placed in a separate layer/package
that contains tests for all modules in the layer. For example, Modules\System Tests \My Module). Test code
cannot reside in the same layer folder structure as the module, or within the module, because it must not be
executable or part of a production environment.

Documentation Guidelines
It's important that you document your module. The following sections provide some guidelines.
Modules
The app.json file for each module must contain a user-friendly title, a short brief, and a description that states its
purpose.
Public API
Every publicly accessible object must have developer facing documentation that follows the XML documentation
comments standard.
Public Objects
Public objects, such as codeunits, tables, pages, and so on, must have a summary that states what the object is
used for.

/// <summary>
/// Lorem ipsum dolor sit amet, consectetur adipiscing elit.
/// </summary>

Public Functions
Public functions must have a summary, a parameter description, and a return value description. The following is
an example.

/// <summary>
/// Maecenas sodales posuere ligula eu maximus.
/// </summary>
/// <param name="Lorem">The current language ID</param>
/// <param name="ipsum ">The CaptionClass expression to resolve</param>
/// <returns> Fusce in tristique massa, tincidunt tempor libero.</returns>

See Also
Getting Started with Modules
Create a New Module in the System Application
Module Architecture
Get Started with Modules in the System Application
2/6/2023 • 2 minutes to read • Edit Online

This topic provides information about requirements for working with modules in the System Application.

AL
Get familiar with development in AL. For more information, see Get Started with AL.

Git
Familiarize yourself with Git. For a quick introduction, see git - the simple guide.

Setup Environment
For details about how to set up an environment for AL development, see Set up your environment.

Building a new module


Have you decided to build a new module? For more information, see Create a new module.

Modifying an existing module


Want to improve an existing module? For more information, see Change a module.

Have an issue?
Please open an issue.

See Also
Module Architecture
Create a module
Set Up an Environment for Developing a Module
2/6/2023 • 3 minutes to read • Edit Online

This topic describes how to set up an environment for developing a module in the System Application.

Requirements
You must have a GitHub account.
You are familiar with the basics of Git, and have the application available. You will use Git to access the
GitHub repository.
Docker is installed. You will use it to run Business Central as a self-contained application.
BcContainerHelper is installed. You will use it to create a Docker container.
Demo or Partner license for Business Central

Get the Repository On Your Local Machine


1. Open the ALAppExtensions Repository, and choose Fork to create a fork of the repository.
2. Choose Code , and then copy the URL under code to clone the forked repository.
The URL looks like https://github.com/<*username*\>/ALAppExtensions.git , and <username> is your
GitHub username.
3. Open PowerShell, and then open the directory in which you want to keep the repository files.
4. Run the git clone <URL> command. Replace <URL> with the URL you copied in step 3.
5. Open Visual Studio Code, and then go to the System Modules folder in the cloned repository.
6. Run the code AL AppExtensions/Modules/System command.
7. In the System folder, open the app.json and note the version that is listed. You will need that in step 3
in the process of setting up a Docker container.
8. Modify the settings.json file in Visual Studio Code to include paths to .NET assemblies. The following is an
example of how to set the "al.assemblyProbingPaths" parameter. The path to the assemblies can differ, for
example, depending on where you keep them or the version you want to use.

"al.assemblyProbingPaths": [
"C:/Windows/Microsoft.NET/Framework64/v4.0.30319",
"C:/bcartifacts.cache/onprem/19.0.29894.30693",
"C:/WINDOWS/assembly"
],

For more information about the settings.json, see User and Workspace Settings.

Set Up a Business Central Docker Container


1. In PowerShell, import the BcContainerHelper module by running the Impor t-Module
BcContainerHelper command. This loads the functions from the module.
2. Run the New-BcContainerWizard command. This opens a new PowerShell window and allows you to
configure your AL Language development environment container.
3. Complete the steps in the wizard. Make the following changes to the default values.
a. On the Local Docker Container or Azure VM step, choose a local docker container.
b. On the Authentication, Username/Password Authentication step, choose options a , b or c .
c. On the Container Name step, enter a name.
d. On the Version step, choose options e or f , depending on whether you want a sandbox or on-
premises build.
Enter the version from ALAppExtensions/Modules/System/app.json after selecting option e or f .
e. Country, US is fine.
f. Test Toolkit, if you have a partner license, you may choose any option. If you only have a demo
license, choose option d , No Test Toolkit .
g. Premium Plan, not required.
h. Create Test Users, not required.
i. AL Base App Development, we will need this as we will work on the System Application.
j. Export AL Base App, not required as we will not be working on BaseApp.
k. AL Language Extension, not required.
l. License, put in the path to your license file.
m. Database, default option a.
n. Multitenant, non-multitenant setup.
o. We will then put in ! to use the default option choices for the rest of the options.
4. At the end of the configuration, you should be presented with the following script:

$containerName = 'mydemo'
$password = 'P@ssw0rd'
$securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$credential = New-Object pscredential 'admin', $securePassword
$auth = 'UserPassword'
$artifactUrl = Get-BcArtifactUrl -type 'OnPrem' -country 'w1' -select 'Latest'
$licenseFile = '<Path to license file>'
New-BcContainer -accept_eula `
-containerName $containerName `
-credential $credential `
-auth $auth `
-artifactUrl $artifactUrl `
-includeTestToolkit `
-includeTestLibrariesOnly `
-licenseFile $licenseFile `
-includeAL -doNotExportObjectsToText `
-updateHosts

NOTE
If you copy the script, remember to update the path to the license file ($licenseFile). Also, if you are using a demo
license, remove the -includeTestToolkit and -includeTestLibrariesOnly options.

5. Run the script to create the Docker container. This can take some time if you are running it for the first
time.
See Also
Getting Started with Modules
Create a New Module in the System Application
Module Architecture
Create a New Module in the System Application
2/6/2023 • 4 minutes to read • Edit Online

This topic provides an overview of how to create a new module in the System Application.

Requirements
1. Familiarity with development in AL. For more information, see AL Development.
2. Your development environment is ready. For more information, see Set Up an Environment for Developing a
Module.

NOTE
Your environment must have the correct symbols. Go get those, in Visual Studio Code, press F1 , and then choose AL:
Download Symbols . Also, make a note of the ser ver and ser verInstance settings. You will add that information to
the launch.json file.

Create a New Module


The following sections provide an example of how to contribute a new module. The example is based on the
XmlWriter module, which is published in the AlAppExtensions repository. That contribution added a wrapper
module to provide support for the XmlWriter, and the steps in this topic will recreate the pull request for the
XmlWriter module. If you want to view the original pull request, it's available here: Pull Request 7876.
Set Up Visual Studio Code for Module Development
Open the launch.json , file and update the ser ver , ser verInstance , and authentication settings, as described
in Set Up Your Development Environment.

"server": "http://YourDockerContainerName",
"serverInstance": "BC",
"authentication": "UserPassword",

Open the settings.json file, and update the al.assemblyProbingPaths , as described in Set Up a Development
Environment.
Create a Branch
To create a branch, run the git checkout -b "YourFeatureBranchName" command. Afterward, you can start
creating a new module.
Add the New Module
Before you create a new module, make sure you are familiar with the general architecture of system modules.
For more information, see Module Architecture.
We'll start by creating a new folder named XmlWriter in the System folder, where we will add an app.json file.
The app.json file will contain the general details of the module.
{
"id": "215b484f-9fbf-437c-bc6e-67e2c0f283b0",
"name": "XMLWriter",
"publisher": "Microsoft",
"brief": "Write XML quickly with System.Xml.XmlTextWriter.",
"description": "Provides a fast, non-cached, forward-only way to create streams or files with XML
data that conforms to guidelines for W3C Extensible Markup Language (XML) 1.0 and Namespaces.",
"version": "17.0.0.0",
"privacyStatement": "https://go.microsoft.com/fwlink/?linkid=724009",
"EULA": "https://go.microsoft.com/fwlink/?linkid=2009120",
"help": "https://go.microsoft.com/fwlink/?linkid=2103698",
"url": "https://go.microsoft.com/fwlink/?linkid=724011",
"logo": "",
"dependencies": [
{
"id": "7e3b999e-1182-45d2-8b82-d5127ddba9b2",
"name": "DotNet Aliases",
"publisher": "Microsoft",
"version": "17.0.0.0"
}
],
"screenshots": [],
"platform": "17.0.0.0",
"idRanges": [
{
"from": 1483,
"to": 1484
}
],
"target": "OnPrem",
"contextSensitiveHelpUrl": "/dynamics365/business-central/"
}

NOTE
After we finish developing our module, we will need to update the app.json file to ensure that the versions and
idRanges are correct. We can easily verify the version by checking the app.json in other modules in the System
Application. The idRanges must reflect the IDs used in the module.

Next, create the src folder under System/XmlWriter . This folder will contain our source code. We will create an
internal implementation codeunit named XmlWriterImpl.Codeunit.al in the src folder.
After adding the implementation functions, the implementation codeunit will look as follows.
codeunit 1484 "XmlWriter Impl"
{
Access = Internal;

procedure WriteStartDocument()
begin
StringBuilder := StringBuilder.StringBuilder();
StringWriter := StringWriter.StringWriter(StringBuilder);
XmlTextWriter := XmlTextWriter.XmlTextWriter(StringWriter);
XmlTextWriter.WriteStartDocument();
end;

procedure WriteEndDocument()
begin
XmlTextWriter.WriteEndDocument();
end;

procedure ToBigText(var XmlBigText: BigText)


begin
XmlTextWriter.WriteString(XmlBigText);
end;

var
StringBuilder: DotNet StringBuilder;
StringWriter: DotNet StringWriter;
XmlTextWriter: DotNet XmlTextWriter;
}

Now that we have created our implementation codeunit, we must add public functions in a facade codeunit with
the functionality that we want to expose. Because the functions are public, we must ensure that these are tested
and documented. To do this, we need to create a facade codeunit. In this example, we'll name the codeunit
XmlWriter.Codeunit.al . The functions call the corresponding functions in the implementation codeunit.
The following is an example of the facade codeunit named XmlWriter.Codeunit.al that includes public
functions and documentation.
/// <summary>
/// Provides helper functions for System.Xml.XmlWriter
/// </summary>
codeunit 1483 "XmlWriter"
{
Access = Public;

/// <summary>
/// Creates the XmlWriter Document
/// </summary>
procedure WriteStartDocument()
begin
XmlWriterImpl.WriteStartDocument();
end;

/// <summary>
/// Closes any open elements or attributes and puts the writer back in the Start state.
/// </summary>
procedure WriteEndDocument()
begin
XmlWriterImpl.WriteEndDocument();
end;

/// <summary>
/// Writes the text within XmlWriter to the BigText variable.
/// </summary>
/// <param name="XmlBigText">The BigText the XmlWriter has to be write to.</param>
procedure ToBigText(var XmlBigText: BigText)
begin
Clear(XmlBigText);
XmlWriterImpl.ToBigText(XmlBigText)
end;

var
XmlWriterImpl: Codeunit "XmlWriter Impl";
}

Now that we have now exposed the functions, the next step is to add tests. To do that, we'll create a new folder
under System Tests , XmlWriter . We will also create an app.json file for the module details and an src folder
for our test code.
We will add the following new file under System Tests/XmlWriter/src , XmlWriterTest.Codeunit.al .
codeunit 139911 "Xml Writer Test"
{
Subtype = Test;

var
Assert: Codeunit "Library Assert";

[Test]
procedure TestWriteStartDocument()
var
XmlWriter: Codeunit "XmlWriter";
XmlBigText: BigText;
begin
// [GIVEN] Initialized XmlWriter
XmlWriter.WriteStartDocument();

// [THEN] Get XmlDocument to text


XmlWriter.ToBigText(XmlBigText);
Assert.AreEqual('<?xml version="1.0" encoding="utf-16"?>', Format(XmlBigText), 'Unexpected text
when creating a Xml Document with XmlWriter');
end;

[Test]
procedure TestWriteEndDocumentNoElement()
var
XmlWriter: Codeunit "XmlWriter";
begin
// [GIVEN] Initialized XmlWriter with root element
XmlWriter.WriteStartDocument();

// [WHEN] Write end document


// [THEN] Expected error to be thrown
asserterror XmlWriter.WriteEndDocument();
Assert.ExpectedError('A call to System.Xml.XmlTextWriter.WriteEndDocument failed with this
message: Document does not have a root element.');
end;
}

After running the tests successfully, changes are complete.


Commit and push your changes and open a PR
To commit your changes, run the git commit -m "Your message" command.
To push your changes, run the git push command.
You can now go to your Github fork and open a pull request in the AlAppExtensions repository.

See Also
Create a .NET Wrapper Module
Become a Contributor to Business Central
"Git" going with extensions
Walkthrough: Contributing to an extension on GitHub
Getting Started with Modules
Create a New Module in the System Application
Module Architecture
Create a .NET Wrapper Module
2/6/2023 • 4 minutes to read • Edit Online

This topic provides a description of how to contribute a .NET wrapper module to Business Central, using the
Regex module as an example. The Regex module is published in the AlAppExtensions repository, and if you
aren't already familiar with the Regex class in .NET, see the .NET documentation.

Converting the Regex architecture


In .NET, the Regex class provides functionality for regular expressions. You can implement the functionality in a
similar way as a system module by creating a Regex codeunit that provides an interface and an internal Regex
implementation that contains the logic.

Wrapping a .NET method


For some methods, you can wrap the .NET method in AL in an internal codeunit and expose the procedure to the
facade. For example, you can wrap the IsMatch method as follows.
/// <summary>
/// Provides functionality to use regular expressions to match text, split text, replace text etc.
/// </summary>
codeunit 3960 Regex
{
Access = Public;

var
RegexImpl: Codeunit "Regex Impl.";

/// <summary>
/// Indicates whether the regular expression finds a match in the input string.
/// </summary>
/// <param name="Input">The string to search for a match.</param>
/// <param name="Pattern">A regular expression pattern to match.</param>
/// <returns>True if the regular expression finds a match; otherwise, false.</returns>
procedure IsMatch(Input: Text; Pattern: Text): Boolean
begin
exit(RegexImpl.IsMatch(Input, Pattern));
end;
}

codeunit 3961 "Regex Impl."


{
Access = Internal;

var
DotNetRegex: DotNet Regex;

procedure IsMatch(Input: Text; Pattern: Text): Boolean


begin
Regex(Pattern);
exit(DotNetRegex.IsMatch(Input))
end;
}

Codeunits in method signatures


Not all .NET Regex classes map so directly to system modules, however. The .NET Regex class also includes
classes such as Match, Group, and Capture, that are used to represent results for regular expression matches.
While it's tempting to wrap these classes in codeunits and use those to output results, you should avoid that
because procedure signatures should not contain codeunits. Instead, use temporary tables to model these
classes. The following code example shows how to implement the Match class in a temporary table.
/// <summary>
/// Provides a representation of Regex Matches that models Match objects in .Net
/// </summary>

/// <remark>
/// For more information, visit /dotnet/api/system.text.regularexpressions.match?view=netcore-3.1.
/// </remark>
table 3965 Matches
{
TableType = Temporary;
Extensible = false;

fields
{
field(1; MatchIndex; Integer)
{
Description = 'The index of the match in the table.';
}
field(2; Index; Integer)
{
Description = 'The position in the original string where the first character of the captured
substring is found.';
}
field(3; ValueBlob; Blob)
{
Access = Internal;
Description = 'Gets the captured substring from the input string.';
}
field(4; Length; Integer)
{
Description = 'Gets the length of the captured substring.';
}
field(5; Success; Boolean)
{
Description = 'Gets a value indicating whether the match is successful.';
}
}
}

The temporary table has all the normal table procedures, and can be extended with procedures if needed. Now
we can write the Match objects, output by .NET, to this table.

codeunit 3961 "Regex Impl."


{
Access = Internal;

var
DotNetRegex: DotNet Regex;
DotNetMatchCollection: DotNet MatchCollection;

procedure Match(Input: Text; Pattern: Text; var Matches: Record Matches)


begin
Regex(Pattern);
DotNetMatchCollection := DotNetRegex.Matches(Input);
InsertMatch(Matches);
end;
}

Avoiding Constructors
The .NET Regex class includes multiple constructors, but we should not expose them in the facade. We can,
however, use constructors internally, as the code previous code example shows.
Removing constructors from a class can cause overloads. One way to get around that is to use the argument-
table pattern. For example, you can construct a temporary table with all optional parameters and internally
implement the logic to apply them.
The .NET Regex class contains three constructors that we want to support:
Regex(Pattern)
Regex(Pattern, RegexOptions)
Regex(Pattern, RegexOptions, MatchTimeout)
In .NET, RegexOptions is an enum with options for matching the pattern (case-sensitivity, ignoring whitespace,
and so on), and MatchTimeout sets a time-out interval for matching. The following example shows how to add
those options to a temporary table.

/// <summary>
/// Table with options to use with Regular Expressions
/// </summary>
table 3966 "Regex Options"
{
Extensible = false;
TableType = Temporary;

fields
{
field(1; IgnoreCase; Boolean)
{
DataClassification = SystemMetadata;
Description = 'Specifies case-insensitive matching.';
}
field(2; Multiline; Boolean)
{
DataClassification = SystemMetadata;
Description = 'Changes the meaning of ^ and $ so they match at the beginning and end
respectively of any line.';
}

...

field(10; MatchTimeoutInMs; Integer)


{
DataClassification = SystemMetadata;
Description = 'A time-out interval in milliseconds, to indicate when the matching should time
out.';
InitValue = -1; // Indicates no time-out
}
}
}

This temporary table makes it straightforward to add overloads to the facade. For each method, there is one
procedure without an options parameter, and one overload with an options table. The following example
illustrates that for the Match procedure.
/// <summary>
/// Searches the input string for the first occurrence of the specified regular expression, using the
specified matching options.
/// </summary>
/// <param name="Input">The string to search for a match.</param>
/// <param name="Pattern">A regular expression pattern to match.</param>
/// <param name="Match">The Match object to write information about the match to.</param>
procedure Match(Input: Text; Pattern: Text; var Matches: Record Matches)
begin
RegexImpl.Match(Input, Pattern, Matches);
end;

/// <summary>
/// Searches the input string for the first occurrence of the specified regular expression, using the
specified matching options.
/// </summary>
/// <param name="Input">The string to search for a match.</param>
/// <param name="Pattern">A regular expression pattern to match.</param>
/// <param name="RegexOptions">A combination of the enumeration values that provide options for
matching.</param>
/// <param name="Match">The Match object to write information about the match to.</param>
procedure Match(Input: Text; Pattern: Text; var RegexOptions: Record "Regex Options"; var Matches:
Record Matches)
begin
RegexImpl.Match(Input, Pattern, RegexOptions, Matches);
end;

See Also
Module Architecture
Getting Started with Modules in the System Application
Set Up an Environment for Developing a Module
Create a New Module in the System Application
Change a Module in the System Application
Change a Module in the System Application
2/6/2023 • 5 minutes to read • Edit Online

This topic provides an overview of how to change an existing module.

Requirements
1. Familiarity with development in AL. For more information, see AL Development.
2. Your local repository and development environment are ready. For more information, see Set Up an
Environment for Developing a Module.

NOTE
Your environment must have the correct symbols. Go get those, in Visual Studio Code, press F1 , and then choose AL:
Download Symbols . Also, make a note of the ser ver and ser verInstance settings. You will add that information to
the launch.json file.

Your changes must follow the guidelines for module architecture. For more information, see Module
Architecture. When changing an existing module, do not introduce breaking changes, that is, make sure that you
do not break existing functionality. Existing tests must still pass, and you should add new tests for the
functionality that you change or add.
Set Up Visual Studio Code for Module Development
Open the launch.json , file and update the ser ver , ser verInstance , and authentication settings, as described
in Set Up Your Development Environment.

"server": "http://YourDockerContainerName",
"serverInstance": "BC",
"authentication": "UserPassword",

Open the settings.json file, and update the al.assemblyProbingPaths , as described in Set Up Your
Development Environment.
Create a Branch
To create a branch, run the git checkout -b "YourFeatureBranchName" command. Afterward, you can start
creating a new module.

Change an Existing Module


The following sections provide an example of how to contribute to an existing module. The example is based on
a previous contribution to the Base64 Convert module, which has been published in the AlAppExtensions
repository. The contribution added support for text encodings other than UTF8. If you're interested, you can view
the original pull request at Pull Request 7676.
Make Changes to a Module
Before making changes, make sure you are familiar with the general architecture of system modules. For more
information, see Module Architecture. You can also check out the article titled How to add a system module for
an example of creating a full system module.
We'll start by adding the functions that we need to support different text encodings to the internal
implementation codeunit. We'll add the following functions to the System/Base64
Conver t/src/Base64Conver tImpl.Codeunit.al implementation codeunit:

procedure ToBase64(String: Text; TextEncoding: TextEncoding): Text


begin
exit(ToBase64(String, false, TextEncoding, 0));
end;

procedure ToBase64(String: Text; TextEncoding: TextEncoding; Codepage: Integer): Text


begin
exit(ToBase64(String, false, TextEncoding, Codepage));
end;

procedure ToBase64(String: Text; InsertLineBreaks: Boolean; TextEncoding: TextEncoding): Text


begin
exit(ToBase64(String, InsertLineBreaks, TextEncoding, 0));
end;

procedure ToBase64(String: Text; InsertLineBreaks: Boolean; TextEncoding: TextEncoding; Codepage:


Integer): Text
var
Convert: DotNet Convert;
Encoding: DotNet Encoding;
Base64FormattingOptions: DotNet Base64FormattingOptions;
Base64String: Text;
begin
if String = '' then
exit('');

if InsertLineBreaks then
Base64FormattingOptions := Base64FormattingOptions.InsertLineBreaks
else
Base64FormattingOptions := Base64FormattingOptions.None;
case TextEncoding of
TextEncoding::UTF16:
Base64String := Convert.ToBase64String(Encoding.Unicode().GetBytes(String),
Base64FormattingOptions);
TextEncoding::MSDos,
TextEncoding::Windows:
Base64String := Convert.ToBase64String(Encoding.GetEncoding(CodePage).GetBytes(String),
Base64FormattingOptions);
else
Base64String := Convert.ToBase64String(Encoding.UTF8().GetBytes(String),
Base64FormattingOptions);
end;

exit(Base64String);
end;

procedure FromBase64(Base64String: Text; TextEncoding: TextEncoding): Text


begin
exit(FromBase64(Base64String, TextEncoding, 1252));
end;

procedure FromBase64(Base64String: Text; TextEncoding: TextEncoding; CodePage: Integer): Text


var
Convert: DotNet Convert;
Encoding: DotNet Encoding;
OutputString: Text;
begin
if Base64String = '' then
exit('');

case TextEncoding of
TextEncoding::UTF16:
OutputString := Encoding.Unicode().GetString(Convert.FromBase64String(Base64String));
TextEncoding::MSDos,
TextEncoding::Windows:
TextEncoding::Windows:
OutputString :=
Encoding.GetEncoding(CodePage).GetString(Convert.FromBase64String(Base64String));
else
OutputString := Encoding.UTF8().GetString(Convert.FromBase64String(Base64String));
end;
exit(OutputString);
end;

We also need to update some of the existing functions in System/Base64


Conver t/src/Base64Conver tImpl.Codeunit.al , while making sure that they keep the same functionality:

procedure ToBase64(String: Text): Text


begin
exit(ToBase64(String, false));
end;

procedure ToBase64(String: Text; InsertLineBreaks: Boolean): Text


begin
exit(ToBase64(String, InsertLineBreaks, TextEncoding::UTF8, 0));
end;

procedure FromBase64(Base64String: Text): Text


begin
exit(FromBase64(Base64String, TextEncoding::UTF8, 0));
end;

We have changed the implementation codeunit, and avoided breaking existing functionality by keeping the
same behavior for existing functions.
Now we'll add public functions in the facade codeunit with the functionality that we want to expose. Because the
functions are public, we need to ensure that they are documented and tested. The functions call the
corresponding functions in the implementation codeunit. We add the following functions to System/Base64
Conver t/src/Base64Conver t.Codeunit.al :
/// <summary>
/// Converts the value of the input string to its equivalent string representation that is encoded with
base-64 digits.
/// </summary>
/// <param name="String">The string to convert.</param>
/// <param name="TextEncoding">The TextEncoding for the input string.</param>
/// <returns>The string representation, in base-64, of the input string.</returns>
procedure ToBase64(String: Text; TextEncoding: TextEncoding): Text
begin
exit(Base64ConvertImpl.ToBase64(String, TextEncoding));
end;

/// <summary>
/// Converts the value of the input string to its equivalent string representation that is encoded with
base-64 digits.
/// </summary>
/// <param name="String">The string to convert.</param>
/// <param name="TextEncoding">The TextEncoding for the input string.</param>
/// <param name="Codepage">The Codepage if TextEncoding is MsDos or Windows.</param>
/// <returns>The string representation, in base-64, of the input string.</returns>
procedure ToBase64(String: Text; TextEncoding: TextEncoding; Codepage: Integer): Text
begin
exit(Base64ConvertImpl.ToBase64(String, TextEncoding, Codepage));
end;

/// <summary>
/// Converts the specified string, which encodes binary data as base-64 digits, to an equivalent regular
string.
/// </summary>
/// <param name="Base64String">The string to convert.</param>
/// <param name="TextEncoding">The TextEncoding for the input string.</param>
/// <returns>Regular string that is equivalent to the input base-64 string.</returns>
/// <error>The length of Base64String, ignoring white-space characters, is not zero or a multiple of 4.
</error>
/// <error>The format of Base64String is invalid. Base64String contains a non-base-64 character, more
than two padding characters,
/// or a non-white space-character among the padding characters.</error>
procedure FromBase64(Base64String: Text; TextEncoding: TextEncoding): Text
begin
exit(Base64ConvertImpl.FromBase64(Base64String, TextEncoding));
end;

/// <summary>
/// Converts the specified string, which encodes binary data as base-64 digits, to an equivalent regular
string.
/// </summary>
/// <param name="Base64String">The string to convert.</param>
/// <param name="TextEncoding">The TextEncoding for the inout string.</param>
/// <param name="Codepage">The Codepage if TextEncoding is MsDos or Windows.</param>
/// <returns>Regular string that is equivalent to the input base-64 string.</returns>
/// <error>The length of Base64String, ignoring white-space characters, is not zero or a multiple of 4.
</error>
/// <error>The format of Base64String is invalid. Base64String contains a non-base-64 character, more
than two padding characters,
/// or a non-white space-character among the padding characters.</error>
procedure FromBase64(Base64String: Text; TextEncoding: TextEncoding; Codepage: Integer): Text
begin
exit(Base64ConvertImpl.FromBase64(Base64String, TextEncoding, Codepage));
end;

We have now exposed the functions. The next steps are to ensure that existing tests pass, and then add new tests
for the functionality that we added.
After verifying that the tests pass, we'll add the following tests to the System Tests/Base64
Conver t/src/Base64Conver tTest.Codeunit.al file.
[Test]
procedure StringToBase64UTF16Test()
var
ConvertedText: Text;
begin
// [SCENARIO] A string variable is converted to base-64 string, binary representation is kept in
UTF16

// [WHEN] The string is converted


ConvertedText := Base64Convert.ToBase64(SampleUTF16Txt, TextEncoding::UTF16);

// [THEN] The converted value is correct


Assert.AreEqual(Base64SampleUTF16Txt, ConvertedText, ConvertionToBase64UTF16Err);
end;

[Test]
procedure FromBase64UTF16StringTest()
var
ConvertedText: Text;
begin
// [SCENARIO] A base-64 string with UTF16 encoding is converted to a regular string

// [WHEN] The base-64 string is converted


ConvertedText := Base64Convert.FromBase64(Base64SampleUTF16Txt, TextEncoding::UTF16);

// [THEN] The converted value is correct


Assert.AreEqual(SampleUTF16Txt, ConvertedText, ConvertionFromBase64UTF16Err);
end;

Commit and Push Changes, and Open a Pull Request


To submit your changes, follow these steps:
1. To commit your changes, run the git commit -m "Your message" command.
2. To push your changes, run the git push command.
You can now go to your GitHub fork and open a pull request in the AlAppExtensions repository.

See Also
Become a contributor
Git going with extensions
Walkthrough: Contributing to an extension on GitHub
Create a new module
Task Scheduler
2/6/2023 • 6 minutes to read • Edit Online

The task scheduler enables you to control when certain operations or processes (in other words tasks) are run.
Basically, a task is a codeunit or report that is scheduled to run at a specific date and time. Tasks run in a
background session between the Dynamics 365 Business Central service instance and database. Behind the
scenes, the task scheduler is used by the job queue to process job queue entries that are created and managed
from the clients.

Create and manage scheduled tasks in AL


A scheduled task is basically a codeunit that runs logic in a background session at a specific time. Optionally, you
can create a second codeunit that contains the logic to handle the task if an error occurs for any reason. This
codeunit is referred to as a failure codeunit.
In AL code, you create and manage the tasks by using the AL methods that are available for the
TASKSCHEDULER data type.

M ET H O D DESC RIP T IO N F O R M O RE IN F O RM AT IO N , SEE. . .

CreateTask Adds a task to run a codeunit at a TaskScheduler.CreateTask(Integer,


specified date and time. Integer [, Boolean] [, String] [,
DateTime] [, RecordId]) Method

TaskScheduler.CreateTask(Integer,
Integer, Boolean, String, DateTime,
RecordId, Duration) Method

SetTaskReady Sets a task to the Ready state. A task TaskScheduler.SetTaskReady(Guid [,


can't run until it's Ready . DateTime]) Method

TaskExists Checks whether a specific task exists. TaskScheduler.TaskExists(Guid) Method

CancelTask Cancels a scheduled task. TaskScheduler.CancelTask(Guid)


Method

To set up a task, create codeunits that contain the logic that you want to run at a scheduled time. Once you have
the codeunits, add code to the application that calls the CreateTask method to schedule a task. The CreateTask
method can also specify the earliest date to run the task.

How task scheduler works


This section describes the flow that a scheduled task goes through.
General flow
When a scheduled task is run, there are two possible execution paths that it can follow: the main path and the
exception path. The main path is used to run the main codeunit and failure codeunits, if any. The exception path
is used to handle errors and control the retry flow when errors occur in the main path. What happens in the
exception path depends on whether the exception is retriable.
Here's a general overview of the process:
1. When a task is created, the task is recorded in table 2000000175 Scheduled Task of the database.
2. When task achieves the ready state and it's scheduled time occurs, a new background session is started.
3. The main path starts:
a. The company is opened and the scheduled task in the table 2000000175 Scheduled Task is
validated.
If any error occurs during this phase, the task fails unless there's a failure codeunit. In which case,
the failure code will run.
b. The task's main codeunit is run:
If main codeunit runs successfully, it's removed from table 2000000175 Scheduled Task .
If an error occurs, the error is passed on to the exception path.
4. The exception path starts:
a. The transaction is rolled back.
b. The exception handling logic is run:
If the exception is retriable, the main codeunit is rerun following the main path.
This retry flow continues in the same session until the task succeeds or until the maximum
number of retries is exceeded, then it fails. The session is then deleted. To understand when
the task will be retried, see Retry Intervals.
If the exception isn't retriable and there's no failure codeunit, the task fails.
If the exception isn't retriable and there's a failure codeunit, the current session is
terminated. A new session is started, and the failure codeunit runs in this session, following
the main path.
If the failure codeunit doesn't handle the error or fails itself, then the exception path is run to
retry the failure codeunit. This retry flow continues in the same session until the task
succeeds or until the maximum number of retries is exceeded. The session is then
terminated.
Detailed flow
The following diagram illustrates the flow in detail.
Retry intervals
When a task's main codeunit or failure codeunit enters the retry flow, it will be rerun at approximately the
following intervals as long as the error persists. The number of retires and the intervals are different for
Business Central online and on-premises.
Online
A codeunit will be retried up to 99 times, according to the following intervals:

RET RY AT T EM P T WA IT T IM E ( M IN UT ES) A F T ER P REVIO US AT T EM P T

1 and 2 .5

3 and 4 1

5 and 6 2

7 and 8 3
RET RY AT T EM P T WA IT T IM E ( M IN UT ES) A F T ER P REVIO US AT T EM P T

9 to 99 5

On-premises
A codeunit will be retried up to nine times, according to the following intervals:

RET RY AT T EM P T WA IT T IM E ( M IN UT ES) A F T ER P REVIO US AT T EM P T

1 and 2 2

3 4

4 to 9 15

Error conditions and retriable exceptions


A task can fail under the various conditions, like:
The company can't be opened.
A SQL connection or transient error occurred with the database.
The Dynamics 365 Business Central service instance restarted while the task was being run.
An upgrade is in progress.
The task scheduler is designed to automatically rerun main and failure codeunits when certain exceptions occur,
instead of just failing on the first attempt. Exceptions that cause the system to rerun a codeunit are referred to as
retriable exceptions. Whether an exception is retriable depends on whether the exception occurs in the main or
failure codeunit and if you're using Business Central online or on-premises.
Retriable exceptions in the main codeunit
If you're running Business Central online, the service controls which exceptions are retriable. With Business
Central on-premises, you can specify retriable exceptions by configuring the Execution Retr y Exceptions
(TaskSchedulerExecutionRetryExceptions) setting on the Business Central Server instance. The Execution Retr y
Exceptions setting is semicolon-separated list of exceptions in a format: Exception1;Exception2;Exception3 . If
you want to specify error code of the exception, use the following format instead:
Exception1:ErrorCode1;Exception2:ErrorCode2.

Retriable exceptions in the main codeunit


Because failure codeunits are designed for error situations, expect for a selected few, almost all exceptions while
running failure codeunits are retriable. It doesn't matter if you're using Business Central online or on-premises.
Even with on-premises, you can't specify retriable exceptions, like you can for main codeunits.

About task sessions and permissions


The task runs in a background session, which means that there's no user interface. The behavior is similar to that
of the StartSession method, where any dialog boxes that would normally appear are suppressed. For more
information about specific dialog boxes, see StartSession method.
The session runs by using the same user/credentials that are used when calling AL code. The user must have
appropriate permissions to the codeunit and any other objects that are associated with the operation of the
codeunit.
NOTE
The device users and delegated admins can't schedule the tasks. To know the restrictions for device users, see Device
licenses.
Delegated admins can test the job queues by making a copy of the job and running it once in the foreground but not as
a recurrent or scheduled task. To know more about limitations for delegated admins, see Restricted access to Business
Central as delegated administrators.

Monitor and troubleshoot


Business Central offers two ways to monitor the flow of scheduled tasks: Azure Application Insights and the
Session Event table. These tools let you follow execution of a task, and investigate errors in failure codeunits.
Application Insights
You can set up Business Central to send telemetry traces to an Application Insights resource in Azure. Once set
up, telemetry data will be sent to the resource as scheduled task moves through the flow. For more information,
see:
Enable Sending Telemetry to Application Insights
Analyzing Task Scheduler Telemetry
Session Event table
From the Business Central web client, you can open the Session Events table by adding table=2000000111 to the
URL. For example: https://businesscentral.dynamics.com/?table=2000000111.

Configure task scheduler for Business Central on-premises


Business Central Server includes several settings related to task scheduler. These settings allow you to enable or
disable task scheduler and manage tasks. For more information, see Configure Business Central Server - Task
Scheduler.

See Also
Task Scheduler Data Type
Developing Extensions
Get Started with AL
Job Queue
2/6/2023 • 2 minutes to read • Edit Online

This article describes how the job queue works in Business Central. A job queue is basically an abstraction that
uses the task scheduler from the platform to enable end users to view, create, or modify jobs that are set to run
in the background. These jobs can be set to run on a recurring schedule.
For information about how users work with the job queue in the client, see Use Job Queues to Schedule Tasks.

Job queue flow


The following diagram illustrates the flow of the job queue:

How job queue works


This section describes the flow that a job queue goes through.
General flow
A job is run when the task scheduler's task is run. For more information, see Task scheduler - detailed flow.
Here's a general overview of the process:
1. When a job queue is created and set to ready state, a scheduled task is created to run, but not before the
Earliest Star t Date/Time .
2. When the scheduled task is picked up by the task scheduler to run, a new background session is started.
3. The background session is run by the Job Queue Dispatcher codeunit:
a. It first checks whether the job should be run or rescheduled.
If the job shouldn't run, it's deleted. Or, in the case of an already running "Category Code", it's
rescheduled.
b. The job queue entry is updated to the In-Progress state, and a job queue log entry is created.
c. The specified Object ID to Run is then started.
If an exception occurs, none of the subsequent steps in the Job Queue Dispatcher path will be run,
but instead, the failure codeunit path will be run.
4. The failure codeunit path runs as follows:
a. An exception is raised and surfaced.
b. The Job Queue Error Handler codeunit is run in a new background session.
a. The job queue entry is updated to the Error state.
b. The errors are saved by using Error Message Management .
c. The job queue entry and job queue log entry are updated with the error.
d. The job queue then either stays in the Error state or is rescheduled:
It will stay in Error state if the Maximum No. of Attempts value has been exceeded
and it's not a recurring job.
It will be rescheduled if the Maximum No. of Attempts value hasn't been exceeded
and it's a recurring job.

About job queue sessions and permissions


The session runs using the same user/credentials that are used when calling AL code. The user that is used is the
user that sets the job to ready state. The user must have appropriate permissions to run the job queue and any
other objects that are associated with the operation of the specified object.
For more information about assigning permissions, see Assign Permissions to Users and Groups in the business
functionality help.

Monitor and troubleshoot


Business Central offers two ways to monitor the flow of job queues: Azure Application Insights and the Session
Event table. These tools let you follow the execution of a job and investigate errors in failure codeunits.
Application Insights
You can set up Business Central to send telemetry traces to an Application Insights resource in Azure. Once set
up, telemetry data will be sent to the resource as job queue moves through the flow. For more information, see:
Enable Sending Telemetry to Application Insights
Analyzing Task Scheduler Telemetry
Session Event Table
From the Business Central web client, you can open the Session Events table by adding table=2000000111 to the
URL. For example: https://businesscentral.dynamics.com/?table=2000000111.

See Also
Task Scheduler. Task Scheduler Data Type
Developing Extensions
Get Started with AL
Using App Key Vaults with Business Central
Extensions
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

Some Business Central extensions make web service calls to non-Business Central services. For example, one
extension might call Azure Storage to read/write blobs. Another extension might call the extension publisher's
web service to do an operation.
These web service calls are typically authenticated, which means the extension must provide a credential in the
call. The credentials enable the other service to accept or reject the call. You can consider the credentials as a
kind of secret to the extension. A secret shouldn't be leaked to customers, partners, or anybody else. So where
can the extension get the secret from? Here is where Azure Key Vault is used. Azure Key Vault is a cloud service
that works as a secure secrets store. It provides centralized storage for secrets, enabling you to control access
and distribution of the secrets.

NOTE
For Business Central online, the app key vault feature is only supported for AppSource extensions.

Getting started
Getting extensions to use secrets from Azure Key Vault involves two areas of work: setting up and configuring
Azure Key Vaults and developing the extensions to use secrets from Azure Key Vault.
Setting up and configuring Azure Key Vaults
An extension can retrieve secrets from one or two different Azure Key Vaults. These key vaults must be created
in Azure, and the Business Central service configured to access key vaults. The setup process is different for
online and on-premises. For more information, see:
Setting up App Key Vaults for Business Central online
Setting up App Key Vaults for Business Central on-premises
Developing the extensions to use secrets from Azure Key Vault
Once you have an Azure Key Vault, you can develop Business Central extensions to retrieve secrets from the key
vault. In short, this work involves specifying the key vault's URL and adding code to retrieve a secret from the
key vault.
For more information, see Using App Key Vault Secrets in Extensions.

See Also
Security Considerations With App Key Vaults
Monitoring and Troubleshooting App Key Vaults
Configuring Business Central Server - Azure Key Vault Extensions
Setting up App Key Vaults for Business Central
Online
2/6/2023 • 3 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

AppSource apps for Business Central can be developed to get secrets from Azure Keys Vaults. The app key vault
feature is readily available for use on the service by all App Source apps. However, there are some onboarding
tasks required.

IMPORTANT
With Business Central online, App key vaults can only be used with AppSource apps. They're not supported with per-
tenant extensions.

TIP
You must also specify secrets in a key vault if you deploy Business Central as part of the Embed App program. Especially if
you must support the Outlook add-in, in which case you must specify secrets for
TEMPORARYDOCUMENTSTORAGEACCOUNT and TEMPORARYDOCUMENTSTORAGEKEY.

For more information about developing extensions with key vaults, see Using Key Vault Secrets in Business
Central Extensions.

Create the Azure Key Vault with secrets


In this task, you create a key vault in Azure, and add the secrets that you want to make available to your
extensions. An extension can use up to two key vaults, so you can create more than one.
There are different ways to create an Azure key vault. For example, you can use the Azure portal, Azure CLI, and
more.
The easiest way is to use the Azure portal. For instructions, see Quickstart: Set and retrieve a secret from Azure
Key Vault using the Azure portal.
For using other methods, see Azure Key Vault Developer's Guide.

Provision the key reader application in your Azure AD tenant


Your Business Central online solution is configured to use an Azure AD application for reading key vault secrets.
The application is called Dynamics 365 Business Central ISV Key Vault Reader . Microsoft manages the
key vault reader application, however, there are a couple tasks that you have to do to enable it. First, the
application must be provisioned on your Azure AD tenant, as described here.
To provision the key vault reader application, use the Azure Active Directory PowerShell module.
1. Open Windows PowerShell as an administrator.
2. Install the Azure Active Directory PowerShell module.
Install-Module AzureAD

3. Import the Azure AD module.

Import-Module AzureAD

4. Connect to your Business Central Azure AD tenant.


a. Run the following command:

Connect-AzureAD

b. Provide your sign-in name and password when prompted.


5. Create an Azure AD service principal using the following command:

New-AzureADServicePrincipal -AppId 7e97dcfb-bcdd-426e-8f0a-96439602627a

7e97dcfb-bcdd-426e-8f0a-96439602627a is the Application (client) ID of Microsoft's centralized Azure AD


application.
This step provisions the application in your Azure AD tenant, where it now "lives" together with your key
vaults.

Grant the key vault reader application permission to your key vaults
The next task is to grant the key vault reader application permission to read secrets from your key vaults. The
steps in this task are done from the Azure portal.
1. Open the key vault in the portal.
2. Select Access policies , then Add Access Policy .
3. Set Secret Permissions to Get .
4. Choose Select principal , and on the right, search for either the application (client) ID 7e97dcfb-bcdd-
426e-8f0a-96439602627a or the display name Dynamics 365 Business Central ISV Key Vault
Reader .
5. Select Add , then Save .

Contact Microsoft to enable the App Key Vault feature


Send an email to bcappkeyvaultonboard@microsoft.com to start the onboarding process following this
guideline:
If it is a new AppSource app, you should send the email after you have published the app on Partner
Center. When the app has been onboarded to the app key vault, you then need to publish a new version
of the app to Partner Center.
If it is an existing AppSource app, you can send the email at any time, but it will only take effect when you
publish a new version of the app to Partner Center.
The onboarding process involves a manual verification step that verifies that you own the AAD tenant that
contains the key vaults.
Provide the following information in the email:
Your AAD tenant ID. Obtain this information from the Azure portal by going to the Azure Active Directory
Overview page.
Your AppSource extensions, including names and App IDs, that should be enabled to read secrets from your
key vaults. Note: It is impor tant that all your AppSource extensions that need access to a key
vault are included, as it is not enough to just set the key vault proper ty in your app.json
manifest files.
Confirmation that the app is already published on AppSource.
Optionally, a screenshot from the Azure portal showing the key vault and its access policies. The screenshot
can help Microsoft catch configuration mistakes early in the process.

See Also
Security Considerations With App Key Vaults
Monitoring and Troubleshooting App Key Vaults
Configuring Business Central Server
Setting up App Key Vaults for Business Central On-
premises
2/6/2023 • 7 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

Business Central extensions can be developed to get secrets from Azure Keys Vaults. This article describes the
tasks required to set up Azure Keys Vaults for storing extension secrets and configure them in your Business
Central deployment.
For more information about developing extensions with key vaults, see Using Key Vault Secrets in Business
Central Extensions.

Prerequisites
To complete the tasks in this article, you need:
An Azure subscription with an Active Directory tenant.
You sign up for an Azure subscription at https://azure.microsoft.com. For information about getting an
Azure AD tenant, see How to get an Azure Active Directory tenant.
A security certificate
Later, you'll have to register and configure an application in Azure AD for reading key vaults. This step
requires a certificate. The certificate is used to prove the application's identity when requesting upon
request. For a production environment, obtain a certificate from a certification authority or trusted
provider.
In a test environment, if you don't have a certificate, then you can create your own self-signed certificate.
For example, on the Business Central server computer, start Windows PowerShell as an administrator.
Then at the prompt, run the following commands:

$cert = New-SelfSignedCertificate -Subject "BusinessCentralKeyVaultReader" -Provider "Microsoft


Strong Cryptographic Provider"
$cert.Thumbprint
Export-Certificate -Cert $cert -FilePath c:\certs\BusinessCentralKeyVaultReader.cer

These commands add a certificate called BusinessCentralKeyVaultReader to the computer's


LocalMachine > Personal (My) certificate store.

Create the Azure Key Vault with secrets


Now, you create one or more key vaults in Azure, and add the secrets that you want to make available to your
extensions. An extension can be set up with one or two key vaults.
There are different ways to create an Azure key vault. For example, you can use the Azure portal, Azure CLI, and
more.
The easiest way is to use the Azure portal. For instructions, see Quickstart: Set and retrieve a secret from
Azure Key Vault using the Azure portal.
After you create the key vault, add the secrets.
For using other methods, see Azure Key Vault Developer's Guide.

Register a key vault reader application in Azure AD


Next, register an application on your Azure AD tenant for reading secrets from the key vaults. When Azure AD
authentication was set up, an Azure AD tenant was created in Azure. Reading key vaults requires a separate
application registration with the Azure AD tenant. You can use an existing application.
The steps in this task are done from the Azure portal.
1. Sign in to Azure portal at portal.azure.com and set the portal to your Azure Active Directory tenant.
2. Register an Azure AD application for the reading key vault.
You add the new application by using the Azure portal. For guidelines, see Register your application with
your Azure Active Directory tenant.
When you add an application to an Azure AD tenant, you must specify the following information:

SET T IN G DESC RIP T IO N

Name The name of your application as it will display to your


users, such as Business Central Key Vault Reader.

Supported account types Specifies which accounts that you would like your
application to support. For purposes of this article, select
Accounts in this organizational director y only .

When completed, the Over view displays in the portal for the new application.
Copy the Application (client) ID . You'll use this information later.
3. Upload the security certificate to the registered application.
In this step, you upload the certificate file that you obtained as part of the prerequisites.
Go to the key vault reader application overview page. Select Cer tificates & secrets > Upload
cer tificate . Follow the instructions to locate and upload the certificate.

Grant the key vault reader application permission to key vaults


In this task, you grant the key vault reader application permission to read secrets from your key vaults.
The steps in this task are done from the Azure portal.
1. Open the key vault in the portal.
2. Select Access policies , then Add Access Policy .
3. Set Secret Permissions to Get .
4. Choose Select principal , and on the right, search for either Application (client) ID or display name for
the key vault reader application.
5. Select Add .
6. Select Save .
At this point, the work in Azure is finished.

Configure the Business Central Server to use the Apps Key Vault
feature
Next, you configure the Business Central Server instance to use the key vault reader application and its
certificate, which you registered in Azure AD, for authenticating to the key vaults.
If you're running a container-based environment, you have two options for configuring the server instance. You
can either do it manually or use the Set-BcContainerKeyVaultAadAppAndCertificate script. Using the Set-
BcContainerKeyVaultAadAppAndCertificate script is simpler and recommended.
Configure a container-based Business Central Server instance
If you are running a container-based environment, use the Set-BcContainerKeyVaultAadAppAndCertificate.ps1
script that is available in the NAV Container Helper GitHub repository at
https://github.com/microsoft/navcontainerhelper/blob/master/ContainerHandling/Set-
BcContainerKeyVaultAadAppAndCertificate.ps1.
Manually configure a Business Central Server instance
To complete this task, you'll need the user name of the service account that runs the Business Central Server.
1. If not already done, import your key vault certificate and its private keys to the local certificate store for
the Business Central server computer.
You can import the certificate either using the MMC snap-in or Import-PfxCertificate cmdlet from a
Windows PowerShell prompt.
For example, the following PowerShell command installs a certificate to the local machine's personal
store:

Import-PfxCertificate -FilePath "C:\certificates\BusinessCentralKeyVaultReader.pfx" -Password


(ConvertTo-SecureString -String "pfxpassword" -AsPlainText -Force) -CertStoreLocation
Cert:\LocalMachine\My\

2. Give the service account used by the Business Central Server instance permission to access the
certificates private key.
To do this using the MMC:
a. Open the MMC snap-in for certificates. See How to: View Certificates with the MMC Snap-in.
b. Expand the Cer tificates (Local Computer) node, expand the Personal node, and then select the
Cer tificates subfolder.
c. In the right pane, right-click the certificate, select All Tasks , and then choose Manage Private
Keys .
d. In the Security dialog box, choose Add .
e. In the Select Users, Computers, Ser vice Accounts, or Groups dialog box, enter the name of
the dedicated domain user account that is associated with Business Central Server, for example,
NETWORK SERVICE. Then, choose the OK button.
f. In the Full Control field, select Allow , and then choose the OK button.
3. Make a note of the certificate thumbprint because you'll need it in the next step. See How to: Retrieve the
Thumbprint of a Certificate.
4. Configure the Business Central Server instance.
Now, you'll configure App Key Vault settings on the server instance. The following table describes the
settings that you must configure:
SET T IN G
( K EY N A M E) VA L UE

Client Certificate Store Location Set to the certificate store location where key vault
(AzureKeyVaultClientCertificateStoreLocation) certificate was stored.

Example:
LocalMachine

Client Certificate Store Name Set to the certificate store name where key vault
(AzureKeyVaultClientCertificateStoreName) certificate was stored.

Example:
MY

Client Certificate Thumbprint Set to the thumbprint for the key vault certificate.
(AzureKeyVaultClientCertificateThumbprint)
Example:
649419e4fbb87340f5a0f995e605b74c5f6d943e

Client ID Set to the Application (client) ID of the key vault


(AzureKeyVaultClientId) reader application registered in your Azure AD tenant.

Example:
ed4129d9-b913-4514-83db-82e305163bec

Enable Publisher Validation Specifies whether extensions can only use key vaults that
(AzureKeyVaultAppSecretsPublisherValidationEnabled) belong to their publishers.

Enabling this setting ( true ) blocks attempts in AL to


read secrets from another publisher's key vault. When
extensions that use key vault secrets are published, you
must provide your Azure AD tenant ID, which is done by
using the Publish-NAVApp cmdlet with the
-PublisherAzureActiveDirectoryTenantId parameter.

Impor tant We recommend that you only set it to


false if you trust all extensions that will be installed.
For more information, see App Key Vaults - Security
considerations.

Example:
true

You can configure the instance using the Business Central Server Administration tool or Set-
NAVServerConfiguration cmdlet.
To use the Set-NAVServerConfiguration cmdlet, start the Business Central Administration Shell as an
administrator, and run the following commands one at a time. Replace brackets with your own values.
Set-NAVServerConfiguration -ServerInstance <serverInstance> -KeyName
AzureKeyVaultClientCertificateStoreLocation -KeyValue <certificate store location>
Set-NAVServerConfiguration -ServerInstance <serverInstance> -KeyName
AzureKeyVaultClientCertificateStoreName -KeyValue <certifcate store>
Set-NAVServerConfiguration -ServerInstance <serverInstance> -KeyName
AzureKeyVaultClientCertificateThumbprint -KeyValue <certificate thumbprint>
Set-NAVServerConfiguration -ServerInstance <serverInstance> -KeyName AzureKeyVaultClientId -KeyValue
<application ID of key vault reader app in Azure>
Set-NAVServerConfiguration -ServerInstance <serverInstance> -KeyName
AzureKeyVaultAppSecretsPublisherValidationEnabled -KeyValue <true|false>
Restart-NAVServerInstance -ServerInstance <serverInstance>

At this point, you can run your extensions that use key vault secrets to read secrets from key vault.

TIP
If your on-premises solution uses the ImportStreamWithUrlAccess method, you must have set up an Azure blob storage
account and stored the account name and account keys in the current subscription's Azure KeyVault using the identifiers
TEMPORARYDOCUMENTSTORAGEACCOUNT and TEMPORARYDOCUMENTSTORAGEKEY. That way, your users can use
the integration with Outlook.

See Also
Using App Key Vaults with Business Central Extensions
Security Considerations With App Key Vaults
Monitoring and Troubleshooting App Key Vaults
Authentication and Credential Types
Configuring Business Central Server
Using Key Vault Secrets in Business Central
Extensions
2/6/2023 • 6 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

This article describes how to code an extension to retrieve secrets from Azure Key Vaults. Secrets are typically
used when the extensions calls a web service. For an overview of app key vaults and secrets, see Using App Key
Vaults with Extensions.
Developing an extension to use secrets from a key vault involves two tasks, as described in this article:
Specifying the Azure Key Vault in the extension's manifest.
Adding code to retrieve the secrets from the key vault.

Preparation
Using secrets requires that you have at least one Azure Key Vault with secrets set up and configured for
use by the service. If you don't already have an Azure Key Vault, see Setting up App Key Vaults for
Business Central online or Setting up App Key Vaults for Business Central on-premises.
For coding, you'll need the URI the Azure Key Vault that stores the secret and the name of the secret itself.
If you don't have this information, you can get it from Azure portal. For instructions, see Quickstart: Set
and retrieve a secret from Azure Key Vault using the Azure portal.

Specify the Azure Key Vault in extensions


You specify the key vaults for an extension in the extension's manifest file (app.json). To specify a key vault, you
add the "keyVaultUrls" to the app.json, and set the value to the key vault's URL. For example, the following
code snippet specifies a key vault that has the URI https://mykeyvault.vault.azure.net :

"keyVaultUrls":[
"https://mykeyvault.vault.azure.net"
]

You can specify up to two key vaults in the app.json, as shown in the following example code snippet:

"keyVaultUrls":[
"https://myfirstkeyvault.vault.azure.net",
"https://mysecondkeyvault.vault.azure.net"
]

Specifying two key vaults ensures a higher availability of secrets, especially if created in two different Azure
regions. At runtime, the Business Central platform will iterate both key vaults until the secret is successfully
retrieved. If one of the key vaults is unavailable for any reason, the extension will continue to execute because
the other key vault will most likely be available.

Add code to retrieve secrets from the key vault


Next, you add code to the extension for reading secrets from the key vault at runtime. To read secrets, you use
the Secrets module of the System Application. Specifically, you'll use codeunit 3800 "App Key Vault Secret
Provider" . This codeunit includes two methods:

M ET H O D DESC RIP T IO N

TryInitializeFromCurrentApp(): Boolean Identifies the calling extension and initializes the codeunit
with the key vaults specified in the extension's manifest.

GetSecret(SecretName: Text, var SecretValue: Text): Retrieves the value of a specific secret from one of the app's
Boolean key vaults.

Look at the following example for a simple page object. The code retrieves the value of the secret named
MySecret in app key vault:

page 50100 HelloWorldPage


{
var
SecretProvider: Codeunit "App Key Vault Secret Provider";
SecretValue: Text;

trigger OnOpenPage();
begin
if SecretProvider.TryInitializeFromCurrentApp() then begin
if SecretProvider.GetSecret('MySecret', SecretValue) then
Message('Retrievedsecret:' + SecretValue)
else
Message('Failed to retrieve secret')
end
else
Message('ERROR:' + GetLastErrorText());
end;
}

The call to the TryInitializeFromCurrentApp method determines the extension that is currently being executed,
then determines the extension's key vaults as specified in the extension manifest. After initialization, the
GetSecret call reads secrets from the key vault.

Security considerations
Keep the following information in mind when you use the App Key Vault feature with your extensions.
Mark methods as NonDebuggable
When your code works with secrets, whether from a key vault or from Isolated Storage, block the ability to
debug relevant methods by using the NonDebuggable Attribute. It prevents other partners from debugging into
your code and seeing the secrets.
Don't pass the App Key Vault Secret Provider to untrusted code
Once the App Key Vault Secret Provider codeunit has been initialized, it can be used to get secrets.
If you pass the codeunit to another method, then that method is also able use it.
If you pass the codeunit to a method in another extension, then the other extension can also use the secret
provider to get secrets.
These conditions may not be what you want, so be careful who you pass the secret provider to.
Enable publisher validation
For on-premises deployments, you can configure Business Central Server to run with or without publisher
validation of key vault secret providers. Publisher validation is controlled by the server's Enable Publisher
Validation (AzureKeyVaultAppSecretsPublisherValidationEnabled) configuration setting. The validation is a
runtime operation that ensures extensions use only key vaults that belong to their publishers. It essentially
blocks attempts in AL to read secrets from another publisher's key vault.
How it works
Publisher validation is done by comparing the key vault's Azure AD tenant ID with the extension publisher's
Azure AD tenant ID. It works this way:
1. When an extension is published by using the Publish-NAVApp cmdlet, the publisher can provide their
Azure AD tenant ID by setting the -PublisherAzureActiveDirectoryTenantId parameter:

Publish-NavApp -ServerInstance <server instance> -Path <path to extension package> -


PublisherAzureActiveDirectoryTenantId <Azure AD tenant ID GUID>

NOTE
An error won't occur if -PublisherAzureActiveDirectoryTenantId isn't set. There is nothing preventing you
from publishing the extension at this point.

2. When the extension runs, it tries to initialize the App Key Vault Secret Provider codeunit.
3. The system compares the key vault's Azure AD tenant ID with the Azure AD tenant ID published with the
extension:
If they match, initialization succeeds.
If they don't match, an error occurs.
Turning off publisher validation
Publisher validation is turned on by default, which is the recommended setting. If it's turned off, the server
instance won't do any additional validation to ensure extensions have the right to read secrets from the key
vaults that they specify. This condition implies some risk of unauthorized access to key vaults that you should be
aware of. So, don't turn off publisher validation unless you trust the extensions that can be potentially installed.
For information about how to turn publisher validation on or off, see Configuring Business Central Server.

Monitoring and troubleshooting


Compiling and publishing
If you get errors when you compile or publish your extension, the most likely reasons are:
You're using an old Visual Studio Code AL extension. Upgrade to the latest AL extension.
Your extension targets an older runtime. Make sure that the "runtime" value in the app.json file is at least
"6.0" .

You're running an old version of Business Central Server. Upgrade to at least version 17.0.
Runtime
For runtime operations, there are two sources that you can use for gathering details:
Windows Event Log of the machine running the Business Central Server.
Application Insights.
These sources provide details about retrieving secrets from key vaults, for calls to the
TryInitializeFromCurrentApp and GetSecret methods from an extension.
Using Application Insights
You can set up extensions to emit telemetry to an Application Insights resource in Azure.
1. Create an Application Insights resource in Azure if you don't have one.
The Application Insights resource will be assigned an instrumentation key. Copy this key because you'll
need it to enable Application Insights in the Business Central administration center.
For more information, see Create an Application Insights resource.
2. In the app.json file of the extension, add the "applicationInsightsKey" :

"applicationInsightsKey":["<instrumenation key>"]

3. Now, you can run your extensions and view data in Application Insights.
For more information, see Viewing telemetry data in Application Insights and Analyzing App Key Vault
Secret Trace Telemetry.

See Also
Get Started with AL
Publishing and Installing Extensions
Configuring Business Central Server
Developing Printer Extensions in Business Central
2/6/2023 • 3 minutes to read • Edit Online

This article provides an overview about how to add code that enables Business Central reports to be sent from
the client directly to a web-connected printer, like an email printer or through a cloud printing service.
Without any customized code, there's no way to send a report directly to a printer for printing. The only way to
print a report from the client is to download it first (as a .pdf file), and then send it to a printer. But you can create
extensions that are designed to send reports to web-connected printers. For example, if you have an email
printer, you create an extension that sends print jobs directly to the printer's email address.

Overview
To accommodate printing, the system publishes two events that you can subscribe to: OnAfterSetupPrinters and
OnAfterDocumentPrintReady. The following figure illustrates the runtime execution of the events:

Throughout the print process, the system compiles the report into a PDF file and passes it in a stream object,
then finally sends the PDF file to the printer.
OnAfterSetupPrinters event
You subscribe to the OnAfterSetupPrinters event to set up different printers that users can use on reports, which
they select from the Printer Selections page. The OnAfterSetupPrinters event is a global integration event that
is published from codeunit 44 Repor t Managements . It has the following declaration:

[IntegrationEvent(false, false)]
local procedure OnAfterSetupPrinters(var Printers: Dictionary of [Text[250], JsonObject]);

The Printers parameter is a Dictionary of [Text, Text] type that includes a collection of key-value pairs that define
different printer setups. The key specifies a name for the printer. The value is a JSON object that specifies
settings supported by the printer. The settings include information like paper size, paper trays, default copies,
and more. The JSON object is referred to as the payload.
The OnAfterSetupPrinters event is raised when the following operations occur:
When you open a page that uses the virtual table Printer as its source.
From page 64 Printer Selections in the base application, when you access the Printer Name field for
selecting a printer for a report. This field has a lookup to the Printer table.
From a report request page, when you select the Print or Preview action for a report. But only if the report
is set up to use a specific printer from the Printer Selections page.
OnAfterDocumentPrintReady
You subscribe to the OnAfterDocumentPrintReady event to specify what happens when the user selects the
Print action on a report request page. You use OnAfterDocumentPrintReady event subscribers to provide
instructions on how and where to send to the report for printing. For example, with email printing, the
OnAfterDocumentPrintReady event subscriber would construct and send an email to a target printer.
The OnAfterDocumentPrintReady event is also a global integration event that is published from codeunit 44
Repor t Managements . It has the following declaration:

IntegrationEvent(false, false)]
local procedure OnAfterDocumentPrintReady(ObjectType: Option "Report","Page"; ObjectId: Integer;
ObjectPayload: JsonObject; DocumentStream: InStream; var Success: Boolean);

The event is raised when the use selects the Print action on the request page of a report. Two parameters of
interest are DocumentStream and ObjectPayload. DocumentStream is an Upstream object that contains the
report data to be printed. The ObjectPayload is a JsonObject type object that combines the printer payload and
report metadata. The report metadata includes information like the company name, MIME type, views, and
more. This combination is referred to as the report payload.

Development Overview
To develop a printer extension, you create codeunits that subscribe to the OnAfterSetupPrinters and
OnAfterDocumentPrintReady events. Plus, you would typically add other objects to support the printing. For
example, you could create a table that stores printer setups and a page that enables users to manage them.
For more information about using the OnAfterSetupPrinters and OnAfterDocumentPrintReady events to create
a printer extension, see Creating a Printer Extension.

See Also
Events in AL
Publishing Events
Raising Events
Subscribing to Events
Creating a Printer Extension
2/6/2023 • 6 minutes to read • Edit Online

This article describes how to use the OnAfterSetupPrinters and OnAfterDocumentPrintReady events to set up
different printers for reports.

Overview
This article uses a simplified printer extension example for sending reports to an email printer. The example
creates a printer extension that sets up a single email printer. Users can then assign the printer to reports from
the Printer Selections page in the client. In this article, you will:
Create two codeunits, one that subscribes to the OnAfterSetupPrinters event and another that subscribes to
the OnAfterDocumentPrintReady event.
Use the SMTP Mail and Mail Management codeunits that are part of the base application for sending the
report via email.

Set up printers using the OnAfterSetupPrinters event


This section describes how to use the OnAfterSetupPrinters event to set up a printer. When completed, users can
select the printer from on the Printer Selections page.
Getting started
1. Create an AL project for the printer extension.
See Get Started with AL.
2. Create a codeunit to use for subscribing to the OnAfterSetupPrinters event.
3. Create a method that subscribes to the OnAfterSetupPrinters event.
At this point, your code would look something like this:

codeunit 50100 SetupPrinter


{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"ReportManagement", 'OnAfterSetupPrinters', '',
true, true)]
procedure OnSetupPrinters(var Printers: Dictionary of [Text[250], JsonObject]);
var

begin

end;
}

For more information about subscribing to events, see Subscribing to Events.


4. Now you can start adding code to the event subscriber method to create the printer payloads.
In this example, you set up a printer named 'My Printer' that has two paper trays: A4 and Custom. There
are two ways of setting values for a payload JSON object. You can add properties (key-value pairs) by
using the Add method, as shown in the example. Or, you can use the ReadFrom method to read the JSON
data from the string into a JsonObject variable (see Using ReadFrom to create the payload).
codeunit 50100 SetupPrinter
{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"ReportManagement", 'OnAfterSetupPrinters', '',
true, true)]
procedure OnSetupPrinters(var Printers: Dictionary of [Text[250], JsonObject]);
var
Payload: JsonObject;
PaperTrays: JsonArray;
PaperTrayA4: JsonObject;
PaperTrayCustom: JsonObject;
begin
// Step 1: Create the paper trays
PaperTrayA4.Add('papersourcekind', 'Upper');
PaperTrayA4.Add('paperkind', 'A4');

PaperTrayCustom.Add('papersourcekind', 'Custom');
PaperTrayCustom.Add('paperkind', 'Custom');
PaperTrayCustom.Add('width', 236);
PaperTrayCustom.Add('height', 322);
PaperTrayCustom.Add('units', 'mm');

// Step 2: Add the paper trays to the list of paper trays


PaperTrays.Add(PaperTrayA4);
PaperTrays.Add(PaperTrayCustom);

// Step 3: Add the required parameters for the payload


Payload.Add('version', 1);
Payload.Add('papertrays', PaperTrays);

// Step 4: Add the printer to the dictionary


Printers.Add('My Printer', Payload);
end;
}

5. At this point, you can compile your project, and publish/install the extension on the tenant to test the
payload.
Open the Printer Selections page in the client. You should see My Printer as an option in the Printer
Name field. If there are errors with payload, you'll get an error when you try to open the Printer Name
field. For more information, see Troubleshooting Printer Payload Errors.
About the printer payload
The event subscriber method has one parameter, which is a dictionary of printers. The key is a name of the
printer. The value is a JSON object that is referred to as the payload. The payload specifies information about a
specific printer. The payload includes several attributes in the following structure:
{
"version": 1,
"description":[default=""],
"duplex":[default=false],
"color":[default=false],
"defaultcopies":[default=1],
"papertrays":
[
{
"papersourcekind":'Upper' | 1,
"paperkind":'A4' | 9,
"units":[default='HI'],
"height":[default=0],
"width":[default=0],
"landscape":[default=false]
}
]
}

There are few required attributes, such as version and papertrays . The papertrays attribute must contain at
least one paper tray setup, which in turn must include the attributes papersourcekind and paperkind . For more
information about the attributes, see Printer Payload.
Using the ReadFrom method to create the payload
The following example illustrates how to create a payload by using the ReadFrom method.

codeunit 50101 SetupPrinter2


{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"ReportManagement", 'OnAfterSetupPrinters', '', true,
true)]
procedure SetupPrinters(var Printers: Dictionary of [Text[250], JsonObject]);
var
Payload: JsonObject;
begin
// Step 1: Read the payload from the text
Payload.ReadFrom('{"version":1,"papertrays":[{"papersourcekind":"Upper","paperkind":"A4"},
{"papersourcekind":"Custom","paperkind":"Custom","width":236,"height":322,"units":"mm"}]}');

// Step 2: Add the printer to the dictionary


Printers.Add('My Printer', Payload);
end;
}

Select the paper tray


A printer can have several paper trays. If a report doesn't specify which paper tray to use or the specified paper
tray isn't present in the printer's setup, a default paper tray is used. The default paper tray is the first one defined
in the papertrays list.
You can change the paper tray for an existing report by subscribing to the OnAfterGetPaperTrayForReport event
and setting a value for a DefaultPage parameter.

[EventSubscriber(ObjectType::Codeunit, Codeunit::"ReportManagement", 'OnAfterGetPaperTrayForReport', '',


true, true)]
procedure GetPaperTrayForReport(ReportID: Integer; var FirstPage: Integer; var DefaultPage: Integer; var
LastPage: Integer)

As an alternative, if you're creating a new report, you can set a paper tray by specifying PaperSourceDefaultPage
property.
report 50103 MyReport
{
PaperSourceDefaultPage = Upper;
...
}

Handle print using the OnAfterDocumentPrintReady event


This section describes how to subscribe to the OnAfterDocumentPrintReady event. You subscribe to the
OnAfterDocumentPrintReady event to define what happens when a user chooses to print a report. The event
subscriber specifies how and where to send the report.
Getting started
1. Create a codeunit to use for subscribing to the OnAfterDocumentPrintReady event.
2. Create a method that subscribes to OnAfterDocumentPrintReady event.
At this point, your code would look something like this:

codeunit 50102 HandlePrintAction


{
[EventSubscriber(ObjectType::Codeunit, Codeunit::ReportManagement, 'OnAfterDocumentPrintReady',
'', true, true)]
procedure OnDocumentPrintReady(ObjectType: Option "Report","Page"; ObjectId: Integer;
ObjectPayload: JsonObject; DocumentStream: InStream; var Success: Boolean);
var

begin

end;
}

For more information about subscribing to events, see Subscribing to Events.


3. Now you can start adding code to the event subscriber method to handle the report payload and send
the report.
The following code sends a report by email to the printer that is named 'My Printer'. In this example, the
printer's email address is 'myprinterb@businesscentral.onmicrosoft.com'.
codeunit 50101 SendReportByEmail
{
[EventSubscriber(ObjectType::Codeunit, Codeunit::ReportManagement, 'OnAfterDocumentPrintReady',
'', true, true)]
procedure OnDocumentPrintReady(ObjectType: Option "Report","Page"; ObjectId: Integer;
ObjectPayload: JsonObject; DocumentStream: InStream; var Success: Boolean);
var
SMTPMail: Codeunit "SMTP Mail";
PrinterNameToken: JsonToken;
PrinterName: Text;
ObjectNameToken: JsonToken;
ObjectName: Text;
DocumentTypeToken: JsonToken;
DocumentTypeParts: List of [Text];
FileExtension: Text;
MailManagement: Codeunit "Mail Management";
SendFrom: Text;
FileName: Text;
Recipients: List of [Text];
begin
begin
// Step 1: Before doing anything, it is important to check the current Success value
if Success then
exit;

// Step 2: Make sure code only runs for reports


if ObjectType = ObjectType::Report then begin

// Step 3: Get report object payload information


ObjectPayload.Get('printername', PrinterNameToken);
PrinterName := PrinterNameToken.AsValue().AsText();
if PrinterName = 'My Printer' then begin
ObjectPayload.Get('objectname', ObjectNameToken);
ObjectName := ObjectNameToken.AsValue().AsText();
ObjectPayload.Get('documenttype', DocumentTypeToken);

// Step 4: Build the email message


DocumentTypeParts := DocumentTypeToken.AsValue().AsText().Split('/');
FileExtension := DocumentTypeParts.Get(DocumentTypeParts.Count);
Recipients.Add('myprinterb@businesscentral.onmicrosoft.com');
SendFrom := MailManagement.GetSenderEmailAddress();
SMTPMail.CreateMessage('Sender', SendFrom, Recipients, 'Hello this is your
report', 'Please take a look');
SMTPMail.AddAttachmentStream(DocumentStream, ObjectName + '.' + FileExtension);

// Step 5: Send the email for print


SMTPMail.Send;
Success := true;
exit;
end;
end;
end;
end;
}

4. At this point, you can compile and publish/install the extension on a tenant to test.
First, make sure that SMTP email is set up on the tenant (see Set Up Email in the Application Help).
Then, on the Printer Selections page, set a report to use 'My Printer', and then run and print the report.
About the report payload
The event subscriber receives the printer payload and combines it with the report metadata, like the report's ID.
This combination is the report payload. The content of the report itself is received as a stream object. You add
code to define how and where to send the report payload for printing. In this example, it's sent as an email.
The report object payload is a JSON object that includes several parameters and values arranged in a specific
structure, as shown in the following example

{
"filterviews":
[
{"name":"Header","tableid":112,"view":"VERSION(1) SORTING(Field3) WHERE(Field3=1(103027))"},
{"name":"Line","tableid":113,"view":"VERSION(1) SORTING(Field3,Field4) WHERE(Field4=1(0..10000))"},
{"name":"ShipmentLine","tableid":7190,"view":"VERSION(1) SORTING(Field1,Field2,Field3)
WHERE(Field2=1(10000))"}
],
"version":1,
"objectname":"Standard Sales - Invoice",
"objectid":1306,
"documenttype":"application/pdf",
"invokedby":"00000000-0000-0000-0000-000000000001",
"invokeddatetime":"2020-01-17T15:33:52.48+01:00",
"companyname":"CRONUS International Ltd.",
"printername":"My Printer",
"duplex":false,
"color":false,
"defaultcopies":1,
"papertray":
{
"papersourcekind":257,
"paperkind":0,
"landscape":false,
"units":0,
"height":1268,
"width":929
}
}

The parameters can be read but not modified at runtime. For more information about the report payload, see
Report Payload.

See Also
Working With and Troubleshooting Payloads
Developing Printer Extensions Overview
Events in AL
Publishing Events
Raising Events
Subscribing to Events
Web Client URL
2/6/2023 • 10 minutes to read • Edit Online

There are several parameters that you can add to the Web client URL to manipulate what is displayed in the
client. For example, you can open a specific company, target a specific page, report, or table. The following URL
displays page 9305 Sales Order List for the CRONUS International Ltd. company:

https://businesscentral.dynamics.com/?company=CRONUS%20International%20Ltd.&page=9305

The following URL opens report 5 Receivables – Payables for the same company:

https://businesscentral.dynamics.com/?company=CRONUS%20International%20Ltd.&report=5

This article describes how you can construct URLs. A well-constructed URL can be useful for including in other
sources, such as emails or Word documents, or sending as hyperlinks to other users.

IMPORTANT
Certain data in the URL, such as filters, could be considered sensitive information. Use discretion if you distribute URLs
that contain filters, or if it's possible, exclude this information from the address.

URL Syntax
The Web client URL has the following syntax:

https://<hostname>[/<aadtenantid>][/<environmentname>]/?[company=<companyname>]&[page|query|report|table=
<ID>]&[tenant=<tenantID>]&[mode=<View|Edit|Create>]&[profile=<profileID>]&[customize]&[bookmark=<bookmark>]&
[captionhelpdisabled=<0|1>]&[showribbon=<0|1>]&[shownavigation=<0|1>]&[showuiparts=<0|1>]&[showheader=
<0|1>]&[isembedded=1]&[pagesize=<number of lines>]&[redirect<0|1>]&[extension=<extensionID>]

The URL consists of two parts; the hostname part and the query string. The hostname part includes the protocol
(https) and the hostname. The query string part includes everything after <hostname> . The query string
determines what content to target.
Syntax Key
The following table describes the notation that is used to indicate the syntax.

N OTAT IO N DESC RIP T IO N

Text without brackets Parameters that you must type as shown.

<> A placeholder for values that you must supply. Don't include
the brackets in the address.

[] Optional parameters. Don't include the brackets in the


address.
N OTAT IO N DESC RIP T IO N

| A set of values from which to choose. Use one of the options


and don't include | in the address.

Building the URL


Use the following guidelines to write URL syntax and create a URL:
You can place parameters in any order after /? . For example, the following URLs will yield the same
results.

https://businesscentral.dynamics.com/?company=CRONUS%20International%20Ltd.&page=9305&mode=View

https://businesscentral.dynamics.com/?page=9305&mode=View&company=CRONUS%20International%20Ltd.

Separate parameters after /? with the ampersand symbol ( & ).


Use %20 for any spaces in values, or similar escape sequences for other characters that can't be used in
URLs.
Enclose values in single quotation marks ( '' ) if they're unescaped.

URL Parameters
The following table describes the parameters of the URL for displaying a page.

PA RA M ET ER DESC RIP T IO N

https Specifies the Internet protocol to use. Only https is


supported.

hostname Specifies the hostname for Dynamics 365, for example,


businesscentral.dynamics.com .

<aadtenantid> Specifies the unique identifier for an Azure Active Directory


(AAD) tenant. The value can be formatted as a GUID or
domain name. It's useful to people who work across multiple
AAD organizations, such as delegated administrators,
support personnel, or external accountants. It allows
explicitly targeting an AAD tenant. If this parameter is
omitted, you'll be directed to the primary AAD tenant or the
same AAD tenant that you're currently signed in to.

<environmentname> (online only) Specifies the display name of sandbox or


production environment to target.

company The name of the company in Dynamics 365 that you want
to target.

If you only have one company, then you can omit this
parameter.

page Opens a page object.


PA RA M ET ER DESC RIP T IO N

query Opens a query object. Note: The TopNumberOfRows


property is ignored when the query opens in the browser.

report Opens a report object.

table Opens a table object. Opening a table requires special


permissions. For more information about opening a table,
see Viewing Table Data.

ID The ID of the page, report, or table to open.

tenant (on-premises only) Specifies the ID of the tenant to connect


to. Use this parameter when Web client is deployed in
multitenant architecture. The tenant that you specify must
be mounted on the Dynamics 365 Business Central service
instance that the Web client connects to. For more
information, see Multitenant Deployment Architecture.

mode Specifies the mode in which to display the page when it


opens. Once the page opens, you can switch modes as
usual, unless restricted by the page itself.

- View
The page can only be viewed. The user can't change data on
the page. Note: Worksheet page types only display in the
edit mode, even if the value is set to View .

- Edit
The user can change data on the page. Note: To use the edit
mode, the Editable Property of the page in Page Designer
must be set to Yes . This mode isn't supported for pages of
the type List, RoleCenter, and CardPart. If you set the value
to Edit , pages of these types still display in the view mode.
For List type pages, the user can modify the list by choosing
Edit List on the page.

- Create
Opens a blank page that enables the user to create a new
item.

Note: The Create mode isn't supported for pages of the


type CardPart, List, ListPart, RoleCenter, and Worksheet. For
pages of the type CardPart, List, and ListPart, the page
displays in the view mode. Don't use this mode for
Worksheet pages; otherwise you'll get an error when you try
to open the page.
PA RA M ET ER DESC RIP T IO N

profile Specifies the ID of the profile to open, such as accountant


or order processor .

It's possible for two or more profiles have the same ID.
Profiles can have a scope of either system or tenant. Also,
tenant profiles can be either user-defined (added by using
the Profiles page in the client) or extension-based (added
by an extension). Among these different types, the IDs of
some profiles might be the same. If there's more than one
profile with the same ID as you provide, the profile is
selected as follows:
1. If there's a matching system profile, it's used.
2. If there's a matching user-defined tenant profile, it's
used.
3. If there's only one matching extension-based profile,
it's used.
4. If there are two or more extensions-based profiles
with the same ID, then the error message
More than one profile has the ID '<ID>'
within the Tenant scope.
appears. In this case, you can't use the profile
parameter for this profile.

customize Opens the profile for customization, enabling you to change


the layout of pages as seen by users of the profile. If you
omit the profile , then the default profile opens. For more
information, see Customizing the Workspace for Profiles
(Roles) in the Business Central Application Help.

bookmark Specifies a record in the underlying table of the page. The


value of a bookmark is an alphanumeric string of characters,
for example, 27%3bEgAAAAJ7CDAAMQA5ADAANQA4ADkAMw%3d%3
.

For the page types Card, CardPart, and Document, the


bookmark specifies the record that is shown in the page. For
page types List, ListPart, and Worksheet, the bookmark
specifies the record that is selected in the list on the page.

Impor tant: Bookmarks are generated automatically. You


can only determine a value for the bookmark by displaying
the page in the Web client and looking at its address. So, a
bookmark is only relevant when the address you're working
with was copied from another page instance.

captionhelpdisabled Specifies that the ability to look up Help by selecting a field


caption is disabled.

If you want the Help look up from the field captions, either
omit this parameter or set its value to 0 , such as
captionhelpdisabled=0 .

If you don't want the Help lookup from field captions, set the
value to 1 , such as captionhelpdisabled=1 .

Note: For this parameter to take effect, add it at the first


request when the user signs in. Adding the parameter on an
existing session has no effect.
PA RA M ET ER DESC RIP T IO N

showribbon Specifies whether to show the action bar on pages when


they open. To show the action bar, omit this parameter or
use showribbon=1 . To hide the action bar, use
showribbon=0 .

When you hide the action bar, it will remain hidden as you
move to different pages, until you refresh or reload the
browser or use showribbon=1 in the URL. Once you move
to another page, the parameter is no longer shown in the
URL, even though it's still in effect.

shownavigation Specifies whether to show the navigation bar when the


specified page opens. To show the navigation bar, omit this
parameter or use shownavigation=1 . To hide the
navigation bar, use shownavigation=0 .

When you hide the navigation bar, it will remain hidden as


you move to different pages, until you refresh or reload the
browser or set shownavigation=1 in the URL. Once you
move to another page, the parameter is no longer shown in
the URL, even though it's still in effect.

showuiparts Specifies whether to show UI parts when the specified page


opens. To show parts, omit this parameter or use
showuiparts=1 . To hide parts, use showuiparts=0 .

This parameter only affects parts that are shown in


FactBoxes. Once you move to another page, the parameter
is cleared.

showheader Specifies whether to show the Dynamics 365 Business


Central header and its functionality. (This was introduced in
Business Central 2020 release wave 1, update 16.2.)

The header is the bar at the top of pages. It gives access to


the general functionality like Tell Me , Notifications , My
Settings , and more. To show the header, omit this
parameter or use showheader=1 . To hide the header, use
showheader=0 .

When hidden, functionality that has a keyboard shortcut,


like Tell Me , is still accessible by the shortcut. The parameter
is preserved when you move to other pages and if you
refresh or reload the browser.

Note: The help pane isn't available when the header is


hidden. Pressing Ctrl+F1 opens a Business Central help
article on Microsoft Docs instead of the help pane.
PA RA M ET ER DESC RIP T IO N

isembedded Specifies to open the Business Central Web client in the


embedded mode. To set the embedded mode, use
isembedded=1 .

This parameter is intended for use when Business Central


Web client is embedded in another web application, like
SharePoint. The embedded mode hides the Dynamics 365
Business Central header and adjusts how navigation
works to suit the web application. For more information, see
Embedding Business Central Web Client in Other Websites.

Note: The help pane (Ctrl+F1) and company switcher


(Ctrl+O) aren't available in the embedded mode. Pressing
Ctrl+F1 opens a Business Central help article on Microsoft
Docs instead of the help pane.

pagesize Specifies the number of lines to display in a list. For example,


pagesize=10 specifies that 10 lines will be displayed. The
default value, if the parameter isn't specified, is 20

The parameter applies only to pages that contain a


repeater control. It's intended for use when Business
Central Web client is embedded in another web application,
like SharePoint. For more information, see Embedding
Business Central Web Client in Other Websites.

redirect Specifies whether users are presented with an option to


download the Business Central Mobile App when they open
the Web client in a mobile browser to improve the user
experience.

If you don't want to give users this option, set the value to
0 , such as redirect=0 .

extension Specifies the unique identifier (ID) of an extension that is


deployed on the environment. This parameter is typically
used during the development of the specified extension in a
non-production environment. When this parameter is set,
only the specified extension is available in the client, and the
client opens in Designer. All other extensions are ignored and
not visible. This parameter enables you to isolate and focus
on the behavior of the specified extension only.

An extension ID is a 32-digit GUID, such as


72CC5E27-BD97-4271-AF55-F77E4471E493 . You set this
parameter using the format extension={GUID} , for
example:

&extension={72CC5E27-BD97-4271-AF55-F77E4471E493}

You can determine an extension ID by opening the extension


in Visual Studio Code and looking in the app.json file. Or, you
can run the Get-NAVAppManifest cmdlet on the extension
package.

Filtering Data on the Page


You can filter the data that is displayed in the page by using the filter parameter. The filter parameter let you
display specific records from the underlying table of the page.
Example
The following address displays data in page 9305 only for the customer who has the Sell-to Customer
No.=10000 and the Location Code =Blue.

https://businesscentral.dynamics.com/?company=CRONUS%20International%20Ltd.&page=9305&filter='Sell-to
Customer No.' IS '10000' AND 'Location Code' IS 'BLUE'

Filter Syntax
The filter has the following syntax.

&filter='<field>' IS '<value>'[ AND '<field>' IS '<value>']

Include a space or %20 before and after the IS and AND operators. You can add the filter anywhere in the
address after /? .
Filter Parameters
The following table describes the filter parameters.

PA RA M ET ER DESC RIP T IO N

field The name of the table field on which to filter.

IS Specifies the equal operator.

value The value of the table field on which to filter.

AND Use this parameter to specify more than one filter. It specifies
an "and" operator for adding additional filters. Place AND
between each additional filter.

To be included in the page data, the table record must match


values for all fields in the filter.

See Also
Viewing Table Data
Linking to the Dynamics 365 Business Central App
2/6/2023 • 4 minutes to read • Edit Online

The protocol handler for the Business Central Mobile App lets you construct a URL for starting the app on a
device, such as a phone or tablet. You can then distribute this URL by e-mail or from a Web page to the users.
The Business Central Mobile App URL is based on the ms-businesscentral URI scheme, which is registered
automatically when the app is installed. Invoking a URL based on this scheme will start the app with the
provided parameters.

Constructing the URL


To construct a URL, start with ms-businesscentral scheme, and then add additional parameters as needed. Some
parameters are required and others are optional.
The structure of a Business Central Mobile App link is very similar to links for the Web client, and has the
following syntax:

ms-businesscentral://[<hostname>][/<aadtenantid>][/sandbox]/[?<parameter>=<value>[&<parameter>=<value>]]

[] indicates an optional parameter; all other parameters are required.


<> indicate values that you must supply. Do not include the brackets in the address.

Parameters
The following table describes the parameters for the main part of the URL, which are the parameters up to and
including [/sandbox]/ .

PA RA M ET ER DESC RIP T IO N EXA M P L E

hostname Domain name for the Dynamics 365 ms-


Business Central solution or IP address businesscentral://businesscentral.dynamics.com/
of the computer/server that hosts it.
This is required for an ISV Embed ms-businesscentral:///
solution. For standard Business
Central, you use ms-
businesscentral.dynamics.com or businesscentral://businesscentral.mysolution.com/

you can omit this parameter.

aadtenantid The unique identifier for an Azure ms-


Active Directory (AAD) tenant. The businesscentral://businesscentral.mysolution.com/mysolutionaadtenant.onmicro
value can be formatted as a GUID or
domain name. This is useful to those
who work across multiple AAD
organizations, such as delegated
administrators, support personnel or
external accountants, because it allows
explicitly targeting an AAD tenant. If
this is omitted, you will be directed to
the primary AAD tenant or the same
AAD tenant that you are currently
signed in to.

sandbox Specifies that the URL should target ms-


the Dynamics 365 Business Central businesscentral:/businesscentral.dynamics.com/sandbox/
sandbox environment instead of a
production environment. ms-
businesscentral://businesscentral.mysolution.com/sandbox/

The following table describes the optional parameters that are indicated by
[?<parameter>=<value>[&<parameter>=<value>]] in the syntax. These parameters are referred to as the query
parameters.

PA RA M ET ER DESC RIP T IO N EXA M P L E

page The ID of the page that you want to ms-businesscentral:///?page=21


open directly.
ms-
businesscentral://businesscentral.mysolution.com/?
page=21
PA RA M ET ER DESC RIP T IO N EXA M P L E

bookmark The bookmark of the record you want ms-businesscentral:///?


to open. The value of a bookmark is an bookmark=19%3bGwAAAAJ7BDEAMAAwADA%3d
alphanumeric string of characters, for
example, ms-
businesscentral://businesscentral.mysolution.com/?
19%3bGwAAAAJ7BDEAMAAwADA%3d . bookmark=19%3bGwAAAAJ7BDEAMAAwADA%3d

For the page types Card, CardPart, and


Document, the bookmark specifies the
record that is shown in the page. For
page types List, ListPart, and
Worksheet, the bookmark specifies the
record that is selected in the list on the
page.

Impor tant: Bookmarks are generated


automatically. You can only determine
a value for the bookmark by displaying
the page in the client and looking at its
address. Therefore, a bookmark is only
relevant when the address you are
working with has been copied from
another instance of the page.

filter The filter you want to apply to the ms-businesscentral:///?


page. page9305&filter='No.'%20IS%20'1001'

The filter parameter enables you to ms-businesscentral:///?


page9305&filter='Sell-to-Customer-
display only records from the No.'%20IS%20'10000'%20AND%20'Location-
underlying table of the page that have Code'%20IS%20'BLUE'
specific values for one or more fields.
For more information about filters, see ms-
Filtering Data on the Page. businesscentral://businesscentral.mysolution.com/?
page9305&filter='No.'%20IS%20'1001'

ms-
businesscentral://businesscentral.mysolution.com/?
page9305&filter='Sell-to-Customer-
No.'%20IS%20'10000'%20AND%20'Location-
Code'%20IS%20'BLUE'

profile Specifies the ID of the profile to open, ms-businesscentral:///?


such as accountant or profile=BUSINESS%20%MANAGER
order processor .
ms-
businesscentral://businesscentral.mysolution.com/?
Be aware that it is possible for two or profile=BUSINESS%20%MANAGER
more profiles have the same ID.
Profiles can have a scope of either
system or tenant. In addition, tenant
profiles can be either user-defined
(added by using the Profiles page in
the client) or extension-based (added
by an extension). Among these
different types, the IDs of some
profiles might be the same. When
there is more than one profile with the
same ID as the one you provide, the
process for launching the profile is as
follows:
1. If there is a matching system
profile, it is used.
2. If there is a matching user-
defined tenant profile, it is
used.
3. If there is only one matching
extension-based profile, it is
used.
4. If there are two or more
extensions-based profiles with
the same ID, then the error
message
More than one profile has
the ID '<ID>' within the
Tenant scope.
appears. In this case, you
cannot use the profile
parameter for this profile.
PA RA M ET ER DESC RIP T IO N EXA M P L E

customize Opens the profile for customization,


enabling you to change the layout of
pages as seen by users of the profile. If
you omit the profile , then the
default profile opens. For more
information, see Customizing the
Workspace for Profiles (Roles) in the
Business Central Application Help.

company The company that you want to open in ms-


the client. If not provided, the default businesscentral:///?'company=CRONUS%20International%20Ltd.'
company is used.
CRONUS%20International%20Ltd. ms-
businesscentral://businesscentral.mysolution.com/?'company=CRONUS%20Internat

mode Whether the page opens in view, edit, ms-businesscentral:///?


or create mode. view only lets you page=21&mode=create
see the data on the page, not modify
data. edit lets you to modify data ms-
businesscentral://businesscentral.mysolution.com/?
on the page. create lets you to page=21&mode=create
modify data on the page and add new
entities.

The query parameters can be in any order. However, the first parameter must be preceded by the ? symbol,
and any additional parameters must be preceded by the & symbol.

See Also
Web Client URL
Introducing the Business Central Mobile App
Instrumenting an Application for Telemetry
2/6/2023 • 2 minutes to read • Edit Online

This article describes how you can implement custom telemetry signals in your application for emitting
telemetry data. This data can then be collected and visualized for analyzing the application against the desired
business goals, troubleshooting, and more.

Telemetry overview
One aspect of event logging is the data collection about the working and deployment infrastructure of an
application to diagnose conditions and troubleshoot problems that affect its operation and performance. For
example, this type of event logging includes Business Central Server events and trace events like SQL and AL
method (function) traces.
Another aspect of logging is telemetry, which is the collection of data about how your application works in
production. Telemetry can tell you about specific activities that users perform within the application in the
production environment. Telemetry also helps troubleshooting in those instances where you aren't able to
reproduce the conditions experienced by the user or have no access to the user's environment. Telemetry can be
divided into different categories, like: telemetry for engineering, telemetry about the business, telemetry for
customers.

Creating custom telemetry signal


There are two different resources where telemetry trace signals can be sent for monitoring and analyzing: Event
Log and Microsoft Azure Application Insights. By default, the Business Central application is instrumented to
emit several system telemetry trace signals to these destinations. Custom telemetry trace signals enable you to
send telemetry data from anywhere in the application code to either of these destinations.
The procedure for creating custom telemetry signals is different for each resource. Your choice might also
depend on whether you're developing for Business Central online or on-premises.

RESO URC E DESC RIP T IO N O N L IN E O N - P REM ISES M O RE IN F O RM AT IO N


RESO URC E DESC RIP T IO N O N L IN E O N - P REM ISES M O RE IN F O RM AT IO N

Application Insights Create custom See...


telemetry signals
that are sent to an
Application Insights
resource in Azure.
Application Insights
is a service hosted
within Azure that
gathers telemetry
data for analysis and
presentation.

Extension developers
can specify whether
the signal is only sent
to the extension
publisher or also to
the VAR partner
telemetry resource.

You create these


custom trace signals
by using the
LOGMESSAGE
method in the code.

Event Log Create custom See...


telemetry trace
signals that are sent
to the Event Log of
the Business Central
Server machine. You
create these custom
trace signals by using
the SENDTRACETAG
method in the code.

NOTE
Using Application Insights is recommended.

See Also
Monitoring and Analyzing Telemetry
Monitoring Business Central Server Events
Creating Custom Telemetry Traces for Application
Insights Monitoring
2/6/2023 • 6 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

This article explains how to develop extensions to send custom telemetry trace signals to Azure Application
Insights for viewing and analyzing.
You can add AL code in extensions to emit messages about activities or operations that users do within the
application. At runtime, the messages can be picked up by an Application Insights resource, which you set up
beforehand. In Application Insights, the custom telemetry events are stored in the traces table.

Set up Application Insights


An Application Insights resource can be configured in two places:
In the app.json file of the extension.
For more information, see Enabling Application Insight on an Extension.
In the tenant on the Business Central Server service/server.
For more information, see Enabling Application Insights.
When you create a custom telemetry trace signal, you can specify a telemetry scope. The telemetry scope
enables you to send a signal only to the Application Insights resource specified in the extension's app.json. Or to
all available resources.

NOTE
Having Application Insights resources configured is not required to create custom signals in AL code.

Create a custom telemetry trace signal


To create a custom telemetry trace signal, use a LOGMESSAGE method in AL code where you want to trigger the
signal. The LOGMESSAGE method defines the information that is sent to Application Insights for a specific
operation or activity.
There are two variations of the LOGMESSAGE method. The difference is that one method uses a dictionary
object to define custom dimensions for the trace signal. The other method includes two overloads so you don't
have to construct a dictionary. You can use these methods in any object, trigger, or method. The methods have
the following signatures:
Using a dictionary
The LOGMESSAGE method for using a dictionary for dimensions has the following signature:

Session.LogMessage(EventId: String, Message: String, Verbosity: Verbosity, DataClassification:


DataClassification, TelemetryScope: TelemetryScope, CustomDimensions: Dictionary of [Text, Text])

Using dimension overloads


The LOGMESSAGE method for using dimension overloads has the following signature:

Session.LogMessage(EventId: String, Message: String, Verbosity: Verbosity, DataClassification:


DataClassification, TelemetryScope: TelemetryScope, Dimension1: String, Value1: String [, Dimension2:
String] [, Value2: String])

Setting the parameters


Use the parameters to build the dimensions, or columns, that will show for the trace in Application Insights.
Message and Verbosity will appear as general dimensions. All other parameters appear as custom dimensions.

PA RA M ET ER DESC RIP T IO N DIM EN SIO N

EventID A text string that assigns an identifier eventId


to the telemetry trace signal. The tag
can consist of letters, numbers, and
special characters. Try to make your
tags unique. For example, use at least
8 characters or a prefix, like Cronus-
0001 and Cronus-0002.

Message A text string that specifies the message


descriptive message for the telemetry
trace signal.

Verbosity* An enumeration that specifies the severityLevel


severity level of the telemetry trace
signal. The value can be Critical , 4 = Critical
Error , Warning , Normal , or 3 = Error
Verbose . 2 = Warning
1 = Normal
0 = Verbose

DataClassification* A DataClassification data type that dataClassification


assigns a classification to the telemetry
trace signal. For more information, see
Data Classifications.

TelemetryScope Scope of emitting the telemetry. telemetryScope


extensionpublisher sends
the custom signal only to the
Application Insight resource
specified in the extension's
app.json file
all sends the custom signal
to Application Insight resource
specified in the extension's
app.json file and on the tenant.

CustomDimensions A dictionary of text that defines the


custom dimensions for the trace signal
in Application Insights. There are
several CustomDimensions that will be
included in traces by default. See
Default CustomDimensions

Dimension1 A text string that specifies the name of


the custom dimension.
PA RA M ET ER DESC RIP T IO N DIM EN SIO N

Value1 A text string that specifies the value of


Dimension1.

Dimension2 A text string that specifies the name of


the custom dimension.

Value2 A text string that specifies the value of


Dimension2.

NOTE
In Application Insights, the name of custom dimension will be prefixed with al . For example, if the dimension string you
define in code is result , then in the trace logged in Application Insights, the name appears as alresult .

D e fa u l t C u st o m D i m e n si o n s

The following table explains CustomDimensions that are automatically included in ALMessage traces that are
sent to Application Insights.

DIM EN SIO N DESC RIP T IO N O R VA L UE

aadTenantId Specifies the Azure Active Directory (Azure AD) tenant ID


used for Azure AD authentication. For on-premises, if you
aren't using Azure AD authentication, this value is common .

alCallerAppName Specifies the name of the extension that emitted the


telemetry signal to Application Insights. This is typically the
base application.

alCallerAppPublishser Specifies the publisher of the extension that emitted the


telemetry signal to Application Insights. This is typically the
publisher of the base application, which is Microsoft .

alCallerAppVersion Specifies the version number of the extension that emitted


the telemetry signal to Application Insights. This is typically
the version of the base application.

alObjectId Specifies the ID of the object that called the LOGMESSAGE


method.

alObjectName Specifies the name of the object that called the


LOGMESSAGE method.

alObjectType Specifies the type of the object that called the LOGMESSAGE
method, like PageExtension for a page extension object.

clientType Specifies the type of client that ran LOGMESSAGE method,


such as Background or Web . For a list of the client types,
see ClientType Option Type.

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

companyName Specifies the company in Business Central


DIM EN SIO N DESC RIP T IO N O R VA L UE

component Dynamics 365 Business Central Ser ver .

componentVersion Specifies the version number of the component that emits


telemetry (see the component dimension.)

environmentName Specifies the name of the tenant environment. See


Managing Environments.

environmentType Specifies the environment type for the tenant, such as


Production , Sandbox, Trial. See Environment Types

extensionName Specifies the name of the extension that called the


LOGMESSAGE method.

extensionId Specifies the ID of the extension that called the


LOGMESSAGE method.

extensionPublisher Specifies the publisher of the extension that called the


LOGMESSAGE method.

extensionVersion Specifies the version of the compiled extension.

deprecatedKeys A comma-separated list of all the keys that have been


deprecated. The keys in this list are still supported but will
eventually be removed in the next major release. We
recommend that update any queries that use these keys to
use the new key name.

telemetrySchemaVersion Specifies the version of the Business Central telemetry


schema.

Examples
The following code snippets create simple telemetry trace signals. They create a critical-level telemetry signal
that is scoped to the signal publisher. For a simple test of this code, add it to the OnRun trigger of a codeunit, and
then run the codeunit.
Using a dictionar y:

trigger OnRun();
var
CustDimension: Dictionary of [Text, Text];
begin
CustDimension.Add('result', 'failed');
CustDimension.Add('reason', 'critical error in code');
LogMessage('MyExt-0001', 'This is a critical error message', Verbosity::Normal,
DATACLASSIFICATION::SystemMetadata, TelemetryScope::ExtensionPublisher, CustDimension);
end;

Using an overload:
trigger OnRun();
begin
LogMessage('MyExt-0001', 'This is a critical error message', Verbosity::Critical,
DATACLASSIFICATION::SystemMetadata, TelemetryScope::ExtensionPublisher, 'result', 'failed', 'reason',
'critical error in code');
end;

Design considerations
For Business Central on-premises, the Diagnostic Trace Level setting on the Business Central Server
instance controls which signals are sent, based on their severity level.
If the Diagnostic Trace Level is set to Warning for example, then Normal and Verbose signals won't
be sent to Application Insights. For more information, see Configuring Business Central Server - General.
For privacy reasons, events that have a DataClassification other than SystemMetadata aren't sent to
Application Insight resources set up on the tenant. During development of your extension, it's good
practice to have a privacy review of the use of LOGMESSAGE calls to ensure that customer data isn't
mistakenly leaked into Application Insights resources.

See Also
Instrumenting an Application for Telemetry
LOGMESSAGE method
LOGMESSAGE method
Monitoring and Analyzing Telemetry
Sending App/Extension Telemetry to Azure
Application Insights
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2020 release wave 2 and later

This article describes how to set up an extension to send telemetry data to Azure Application Insights for
monitoring and analyzing. Business Central emits telemetry data for several operations that occur when
extension code is run. For an overview about the telemetry with Azure Application Insights, see Monitoring and
Analyzing Telemetry.
This feature targets publishers of per-tenant or appsource extensions to give them insight into issues in their
extensions before partners and customers report them.

Get an Application Insights resource in Azure


The first thing to do is to create an Application Insights resource in Azure if you don't have one. For more
information, see Create an Application Insights resource.
The Azure Application Insights resource is assigned a connection string, which you can see on the Over view
page for the resource in Azure. Copy this connection string because you'll need it to enable telemetry in the
app/extension.

Add the Application Insights information to the app/extension


The next step is to add the "applicationInsightsConnectionString" setting the extension's app.json as shown:

"applicationInsightsConnectionString":"<connection string>"

Replace <connection string> with the string that you copied in the Azure Application Insights overview. For
more information about the format of the Azure Application Insights connection string, see Connection Strings.
When done, build the extension package, then publish and install it as usual. When the extension is run from
Business Central, Azure Application Insights gathers the telemetry data for viewing and analyzing.
Prior to runtime version 7.2
Up until runtime version 7.2 you cannot use the "applicationInsightsConnectionString" setting. Instead you
have to use the "applicationInsightsKey" setting which is added using only the instrumentation key from the
Azure Application Insights connection string as shown:

"applicationInsightsKey":"<instrumentation key>"

Where <instrumentation key> is replaced by the key denoted in the connection string as
InstrumentationKey=<instrumentation key>;<some other parameters> .
NOTE
Transition to using connection strings for data ingestion in Azure Application Insights by 31 March 2025 . On 31 March
2025, technical support for instrumentation key–based global ingestion in the Azure Application Insights feature of Azure
Monitor will end. After that date, your Azure Application Insights resources will continue to receive data, but Microsoft no
longer provide updates or customer support for instrumentation key–based global ingestion.

See Also
Get Started with AL
Publishing and Installing Extensions
JSON Files
Viewing telemetry data in Application Insights
LogMessage Method
Creating Custom Telemetry Events for Event Log
Monitoring
2/6/2023 • 3 minutes to read • Edit Online

> APPLIES TO: Business Central On-Premises.


This article explains how to create custom telemetry trace events in AL code that will be sent to the Event Log of
the Business Central Server machine.

NOTE
The SENDTRACETAG method is marked as obsolete in Business Central 2020 release wave 2 (v17). You can still use it, but
we recommend that you send traces to Application Insights using the LOGMESSAGE method instead. For more
information, see Creating Custom Telemetry Traces for Application Insights Monitoring.

Create custom telemetry events


To create a custom telemetry event, you use the SENDTRACETAG method in code. You can use the
SENDTRACETAG method in any object, trigger, or method. The SENDTRACETAG method has the following syntax:

SENDTRACETAG(Tag, Category, Verbosity, Message[, DataClassification])

You use the parameters to define the information about the telemetry trace event. This information is can be
consumed by event logging tools, and presented in different ways.

PA RA M ET ER DESC RIP T IO N

Tag A text string that assigns an identifier to the telemetry trace


event. The tag can consist of letters, numbers, and special
characters. Business Central system telemetry events use an
auto-generated, auto-incremented, 7-character tag that
includes numbers and letters, such as 000002Q. and
000013P. Try to make your tags unique from these
telemetry event tags by, for example, using at least 8
characters or a prefix, like Cronus-0001 and Cronus-0002.

Category A text string that assigns the telemetry trace event to a


category that you define. For example, you could have a
category for upgrading, user activity, or reporting.

Verbosity An enumeration that specifies the severity level of the


telemetry trace event. The value can be Critical, Error,
Warning, Normal, or Verbose. This severity level can be used
by Business Central Server to filter out lower-level telemetry
trace events from being emitted. See Viewing and collecting
telemetry data.

Message A text string that specifies the descriptive message for the
telemetry trace event.
PA RA M ET ER DESC RIP T IO N

DataClassification A DataClassification data type that assigns a classification to


the telemetry trace event. For more information, see Data
Classifications.

For example, the following code creates simple telemetry trace events for the five different severity levels.

SENDTRACETAG('Cronus-0001', 'Action', VERBOSITY::Critical, 'This is a critical message.',


DATACLASSIFICATION::CustomerContent);
SENDTRACETAG('Cronus-0002', 'Action', VERBOSITY::Error, 'This is an error message.',
DATACLASSIFICATION::EndUserIdentifiableInformation);
SENDTRACETAG('Cronus-0003', 'Action', VERBOSITY::Warning, 'This is a warning message.',
DATACLASSIFICATION::AccountData);
SENDTRACETAG('Cronus-0004', 'Action', VERBOSITY::Normal, 'This is an informational message.',
DATACLASSIFICATION::OrganizationIdentifiableInformation);
SENDTRACETAG('Cronus-0005', 'Action', VERBOSITY::Verbose, 'This is a verbose message.',
DATACLASSIFICATION::SystemMetadata);

For a simple test of this code, add it to the OnRun trigger of a codeunit, and then run the codeunit. Of course,
you can also call the code from other objects, triggers or functions as well.

View and collect telemetry data


Viewing and collecting telemetry data is done the same way as with other trace events emitted by Business
Central, for example, by using tools like Event Viewer, Performance Monitor, PerfView, or logman.
In Event Viewer, telemetry trace events can be viewed from Applications and Ser vices Logs , in the
Microsoft > DynamicsNAV > Common folder. The custom telemetry trace events are recorded in the
Admin folder. You should be aware that only events with severity level of Warning, Error, and Critical will
appear.
For more information, see Monitoring Business Central Server Events Using Event Viewer.
With other tools like Performance Monitor, PerfView, and logman, you can collect telemetry data by using
Microsoft-DynamicsNAV-Common as the event trace provider.
For more information, see Get Started Monitoring Events.

IMPORTANT
The Business Central Server instance includes a configuration setting called Diagnostic Trace Level ( TraceLevel in the
customsettings.config file) that enables you to specify the lowest severity level of telemetry events to be recorded in the
event log, or even turn off telemetry event logging altogether. If you do not see the expected events, then verify the
Business Central Server instance configuration with an administrator. For information, see Configuring Business Central
Server.

See Also
Instrumenting an Application for Telemetry
Monitoring and Analyzing Telemetry
Monitoring Business Central Server Events
Getting started with Microsoft .NET Interoperability
from AL
2/6/2023 • 3 minutes to read • Edit Online

You can call .NET type members, including methods, properties, and constructors, from AL code. In this article
we will guide you through the process of creating an extension that uses .NET types.

IMPORTANT
.NET Interoperability is only available on-premise. If you want to use this functionality, you must set the
"target": "OnPrem" in the app.json file. For more information, see JSON Files.

Alternatively you can use services such as Azure Functions to call into .NET dlls from AL, which will also work online. For
online training, see Use Azure Functions with Dynamics 365 Business Central.

Enabling .NET Interoperability


.NET interoperability can only be used by applications that target on-premise deployments. See JSON Files for
more information on how to set the correct compilation target and Compilation Scope Overview.

Declaring a .NET package


Using a .NET type in AL is a two-step process. First, you must declare the type in a dotnet package, and then
reference it from code using the DotNet type.
You start by declaring an empty dotnet package in your extension. See the example snippet below.

dotnet
{

It is recommended to have only one package per extension that contains all the .NET types which you will be
using.
You continue by adding a declaration of the assembly that you will be referencing. For this example, we will use
the mscorlib assembly that contains the core .NET types. A dotnet package can contain an unlimited number
of assembly declarations. The name of the assembly must be the one defined in the assembly's manifest. See the
following example snippet.

dotnet
{
assembly(mscorlib)
{
}
}

By default, the compiler only knows about the location of the mscorlib assembly. You can reference any
compatible assembly by providing the compiler with a path to the assembly's containing folder. This can be
achieved by adding the path to assembly's containing folder to the "al.assemblyProbingPaths" setting. Open the
Command Palette Ctrl+Shift+P and choose either User Settings or Workspace Settings and specify the
al.assemblyProbingPaths setting. For example:

"al.assemblyProbingPaths": [
"./.netpackages",
"C:/Program Files/Assemblies"
]

NOTE
Any update to an assembly's code is not automatically detected by the compiler. If an assembly has changed, then you
must restart your development environment.

You continue by adding a reference to a type from the referenced assembly. In this example, we will use
System.DateTime from mscorlib and we will give it the alias MyDateTime . The type must be referenced using its
fully-qualified name. The alias is used for referencing the .NET type from code. If an alias is not provided, the
compiler will use the .NET type name. A .NET assembly declaration can contain any number of type declarations.
See the example below.

dotnet
{
assembly(mscorlib)
{
type(System.DateTime; MyDateTime){}
}
}

Using a .NET type from AL code


From this point on, we can reference the .NET type from AL code using its given alias, as shown in the example
below.

dotnet
{
assembly(mscorlib)
{
type(System.DateTime; MyDateTime){}
}
}

pageextension 50100 CustomerListExt extends "Customer List"


{
trigger OnOpenPage();
var
now: DotNet MyDateTime;
begin
now := now.UtcNow();
Message('Hello, world! It is: %1 ' + now.ToString());
end;
}

Publishing your extension


The AL Language extension, including the AL compiler, and the server to which you publish your code are
completely decoupled. When publishing, the server re-compiles your code and tries to resolve all the references
to external assemblies. In order for the compilation to succeed, the server must be able to locate and load all the
referenced assemblies and types.
The server will search the global assembly cache (GAC), the Add-ins folder, and the Add-in table. You must
manually install any custom assembly in one of these locations.

See Also
Get Started with AL
.NET Control Add-Ins
Subscribing to Events in a .NET Framework Type
Serializing .NET Framework Types
AL Language Extension Configuration
Migrating from .NET Framework to .NET Standard
2/6/2023 • 4 minutes to read • Edit Online

Starting in 2022 release wave 2 (v21), the Business Central Server supports .NET add-ins compiled to target the
.NET Standard runtime. This change currently doesn't affect your .NET add-ins. However, it might affect some
.NET add-ins in the next release (v22). Read this article to learn more.

What's the difference between .NET Framework, .NET Core, and .NET
Standard?
When first released, .NET Framework had one runtime for building and running Windows desktop and Web
applications. The .NET implementation has evolved over the years. Now, to supplement the .NET Framework, we
also have:
.NET Core
The latest .NET implementation, open source and available for multiple operating systems. With .NET Core,
you can build cross-platform console apps and ASP.NET Core Web applications and cloud services.
.NET Standard
The set of fundamental APIs, sometimes referred to as the .NET Base Class Library (BCL) that all .NET
implementations must implement. By targeting .NET Standard, you can build libraries that you can share
across all your .NET apps, no matter on which .NET implementation or operating system they run.
The various .NET implementations target specific versions of .NET Standard.

What are the changes to Business Central server?


In v21, Business Central Server now lets you install and run .NET add-ins that are compiled to target the .NET
Standard runtime. The Business Central Server executable itself is still compiled for the .NET Framework 4.8
runtime as in earlier versions.
The difference in v22 is that the Business Central Server executable will be complied for the .NET 6.0 runtime.

What does this mean for your .NET add-ins?


In v21, you won't have any problems compiling, installing or using .NET add-ins built on the old .NET
Framework, related to this change. The reason is because of the .NET compatibility mode. It isn't necessary to
recompile your .NET to target another .NET runtime right now. For more information about compatibility mode,
go to .NET Framework compatibility mode.
In v22, you'll still be able to use .NET add-ins built on the old .NET Framework. But problems will arise if you
have a .NET add-in that calls another API that's not compatible with the add-in's target runtime. When the add-in
calls the incompatible API, an exception will occur.
We recommend you start converting your .NET add-ins to use .NET Standard to avoid problems in the next
release. Check your add-in code and decide on how to proceed to ensure continued compatibility.
Because .NET add-ins aren't supported in the cloud, consider options for moving some or all scenarios to
technologies that are supported in the cloud, for example, Azure Functions. This action will improve cloud
readiness of the solution even if not yet migrating to cloud.
You can also upgrade add-ins to be .NET Standard compliant. Some of .NET add-ins will be fully compliant
out of the box or easily portable to be .NET Standard compliant, but for other more complex solutions, this
process could involve more work.

Using the Visual Studio .NET Portability Analyzer extension


Use the .NET Portability Analyzer extension from the Visual Studio Marketplace to check for compatibility to .NET
Standard. It analyzes the assemblies. Then, it provides a detailed report on missing .NET APIs that prevent
porting applications or libraries to a specified .NET platform.

NOTE
The Visual Studio .NET Portability Analyzer extension is currently only available for Visual Studio 2019.

After the tool is installed, configure it to define the type of portability analysis needed, such as the target .NET
versions that you want to be compatible with. To do that, complete the following steps:
1. In Visual Studio, select Analyze and then Por tability Analyzer Settings .
2. In the General Settings window, select .NET Standard 2.0 under Target Platforms , and then choose OK .
3. Now, open the project file containing the code that needs to target .NET Standard, right-click the project, and
select Analyze Project Por tability .
This step opens up a Por tability Analysis Results page with and assessment of compatibility, and a list of
recommended changes.

Using the Microsoft ApiPort tool


Microsofts ApiPort tool is another way to check for compatibility to .NET Standard. This tool allows you to
analyze files in case you don't have access to the original source code.
You can download the ApiPort tool at .NET API Portability GitHub repository.
To use the tool, do the following step:
1. Open a command prompt and type ApiPort.exe analyze -f MyLibrary.dll .
The tool can also help analyze projects with dependencies between DLL files and visualize the
dependencies. It's useful in more complex solutions with portability problems.
To analyze dependencies, do the following step:
1. Open a command prompt and type ApiPort.exe analyze -r DGML -f [directory or your solution]

When the command finished, you have a DGML file that can be opened in Visual Studio. Directed Graph Markup
Language (DGML) describes information used for visualization and complexity analysis. It's the format used to
persist code maps in Visual Studio.

See Also
Get Started with AL
.NET Control Add-Ins
Subscribing to Events in a .NET Framework Type
Serializing .NET Framework Types
AL Language Extension Configuration
.NET Control Add-Ins
2/6/2023 • 3 minutes to read • Edit Online

In Dynamics 365 Business Central on-premises you can use existing .NET and Javascript control add-ins from
the AL Language through .NET interoperability. It is recommended that you convert your existing .NET and
Javascript add-ins to native AL control add-ins that are supported both on-premises and in the cloud. For more
information about native AL control add-ins, see Control Add-In Object.
To declare the usage of a .NET or Javascript add-in in AL, you need three critical pieces of information about the
.NET type that represent the interface of the add-in. These are the name of the assembly containing the add-in,
the name of the control add-in, and the name of the class that implements the control add-in. We will show how
to retrieve this information for the Microsoft.Dynamics.Nav.Client.PingPong control add-in that ships with
Business Central.
The name of the assembly can be retrieved from the AssemblyName element in the .csproj file associated
with the .NET project that represents the control add-in. In this case the name of the assembly is
Microsoft.Dynamics.Nav.Client.PingPong .

NOTE
If you do not have access to the .csproj file , you can determine the name of the assembly by following the
instructions in How to: Determine an Assembly's Fully Qualified Name.

The following code sample contains the stub definition of the Microsoft.Dynamics.Nav.Client.PingPong .NET add-
in.
namespace Microsoft.Dynamics.Nav.Client.PingPong
{

/// <summary>
/// Add-in for pinging the server from the client. The client will respond with a pong.
/// </summary>
[ControlAddInExport("Microsoft.Dynamics.Nav.Client.PingPong")]
public class PingPongAddIn : WinFormsControlAddInBase
{

/// <summary>
/// Event will be fired when the AddIn is ready for communication through its API
/// </summary>
[ApplicationVisible]
public event MethodInvoker AddInReady;

/// <summary>
/// Event will be fired when the specified time by the ping has elapsed.
/// </summary>
[ApplicationVisible]
public event MethodInvoker Pong;

/// <summary>
/// Starts the ping process.
/// </summary>
/// <param name="milliseconds">Number of milliseconds before ponging.</param>
/// <remarks>If a milliseconds are less than the minimum then the MinimumValue is used.</remarks>
[ApplicationVisible]
public void Ping(int milliseconds)
{
...
}
}

The next needed piece of information is the namespace-qualified name of the type annotated with the
ControlAddInExport attribute. This is the type that provides the implementation of the control add-in and which
exposes members annotated with the ApplicationVisible attribute to the AL runtime. In this example this is
Microsoft.Dynamics.Nav.Client.PingPong.PingPongAddIn .

The ControlAddInExport attribute's constructor takes as an argument the name of the control add-in, as
represented in the runtime, and in existing C/AL code. In this example, the name of the control add-in is
Microsoft.Dynamics.Nav.Client.PingPong . This was the last component needed to construct a declaration for this
.NET control add-in in AL. The name of the assembly is used in creating the assembly construct, the namespace-
qualified name of the type is used as the first element in the type declaration, and the name of the control add-
in is used as the alias of the type. You complete the declaration by setting the IsControlAddIn property to true.
This property is used to tell the AL compiler to treat the given type declaration as a .NET control add-in
declaration.
Remember to add the setting "AL: Assembly Probing Paths" in the User Settings or Workspace Settings
specifying the path of the folder containing the assembly so that the compiler can access it. For more
information, see Getting started with Microsoft .NET Interoperability from AL.
dotnet
{
assembly("Microsoft.Dynamics.Nav.Client.PingPong")
{
type("Microsoft.Dynamics.Nav.Client.PingPong.PingPongAddIn"; PingPongAddIn)
{
IsControlAddIn = true;
}
}
}

You can now use the Microsoft.Dynamics.Nav.Client.PingPong from AL, just as you use a native control add-in.

page 50100 MyPage


{
layout
{
area(Content)
{
usercontrol(PingPongControl; PingPongAddIn)
{
trigger Pong()
begin
Message('Pong received.');
end;

trigger AddInReady()
begin
Message('Ready');
end;
}
}
}
}

Remarks
Only members of the .NET type implementing the control add-in that are annotated with the
ApplicationVisibleAttribute will be accessible from AL. Usages of .NET control add-ins in C/AL are
automatically converted to AL by the Txt2Al conversion tool, but the code will only compile, if you manually
insert the declaration of the control add-in, as outlined above.
If within the same project you have a native AL control add-in and a .NET add-in with the same name, the .NET
add-in will be the one used.

See Also
Migrating from .NET Framework to .NET Standard Get Started with AL
Control Add-In Object
Getting started with Microsoft .NET Interoperability from AL
Subscribing to Events in a .NET Framework Type
Serializing .NET Framework Types
How to: Determine an Assembly's Fully Qualified Name
AL Language Extension Configuration
Subscribing to Events in a .NET Framework Type
2/6/2023 • 2 minutes to read • Edit Online

With .NET Framework interoperability in Dynamics 365 Business Central objects, you can configure a DotNet
variable to subscribe to events that are published by a .NET Framework type. Events are handled by triggers in
the AL code of the Business Central object.
You start by declaring in AL the usage of two .NET types from the System assembly. The first type is
System.Timers.Timer and it will be used to generate .NET events. The second one is called
System.Timers.ElapsedEventArgs and it is required for creating a subscriber to the Elapsed event emitted by the
Timer type.

dotnet
{
assembly(System)
{
type(System.Timers.Timer; MyTimer) {}
type(System.Timers.ElapsedEventArgs; MyElapsedEventArgs) {}
}
}

You can only subscribe to events that are emitted by global variables of the .NET type marked with the
WithEvents attribute. For all the global variables that are marked with this attribute, the compiler will expose the
events available on the type as triggers on the variable. The syntax for declaring these triggers is
{VariableName}::{EventName}(...ParameterList) , but IntelliSense will offer suggestions for the event name and
autocomplete the parameter list.

pageextension 50101 CustomerListExt extends "Customer List"


{
var
[WithEvents]
timer: DotNet MyTimer;

trigger OnOpenPage()
begin
SetupTimer();
end;

procedure SetupTimer()
begin
timer := timer.Timer(2000);
timer.AutoReset := true;
timer.Enabled := true;
timer.Start();
end;

trigger timer::Elapsed(sender: Variant; e: DotNet MyElapsedEventArgs)


begin
// Print a message when this event is published
Message('%1', e.SignalTime());
timer.Stop();
end;
}
See Also
Getting started with Microsoft .NET Interoperability from AL
Migrating from .NET Framework to .NET Standard .NET Control Add-Ins
Serializing .NET Framework Types
Method Attributes
AL Language Extension Configuration
Serializing .NET Framework Types
2/6/2023 • 6 minutes to read • Edit Online

In Microsoft .NET Framework, serialization is the process of converting an object into a format that can be
transmitted across a network connection. Microsoft .NET Framework interoperability uses serialization for
communication between client-side .NET Framework objects and server-side .NET Framework objects. When
you configure DotNet variables in a Dynamics 365 Business Central object, you can specify .NET Framework
objects to target either the Business Central Windows client or Business Central Server. In some cases, a client-
side object and a server-side object must communicate and share data, such as return values and parameters.
The serialization occurs when the following conditions are true:
When a server-side object is assigned to a client-side object, and vice-versa.
When a server-side object is passed as a parameter in a method call from the server to a client-side
object, and vice-versa.
Serialization requires that the .NET Framework types that are used by the DotNet variables are serializable.
Many types in the Microsoft .NET Framework class library are already serializable. If you are using a .NET
Framework type that cannot be serialized, then you must modify the type to make it serializable.

IMPORTANT
For the Business Central Web client, you cannot implement Microsoft .NET Framework interoperability objects that target
the client.

Making a Type Serializable


There are two ways that you can make a .NET Framework type serializable. You can implement basic serialization
by applying the System.SerializableAttribute attribute to the type or you can implement custom serialization by
using System.Runtime.Serialization.ISerializable interface.
Basic Serialization Using SerializableAttribute
Basic serialization uses the .NET Framework to automatically serialize an object. To implement basic serialization
on a type, you decorate the type with the SerializableAttribute class as shown in the following example.

[Serializable]
public class MyObject
{
code
}

This method requires that you have access to the source code of the .NET Framework assembly.
Basic Serialization of Date Fields
You can use basic serialization only if all data fields in the type are serializable. Fields that are calculated at
runtime cannot be serialized. If a field cannot be serialized, then at runtime, the serialization process will throw
an exception and the AL code execution will fail.
You can exclude fields from the serialization process by decorating the field with the
System.NonSerializedAttribute class.
Custom Serialization Using ISerializable Interface
With custom serialization, you can create an object that controls the serialization of types in another object. This
method is useful when you do not have access to the source code of the assembly that contains the .NET
Framework types that you are implementing with .NET Framework interoperability. The custom object specifies
which types will be serialized and how serialization will be done.
To implement custom serialization, you create a class that implements the ISerializable interface, and decorate
the class with SerializableAttribute. In most cases, you must also implement the
System.Runtime.Serialization.ISerializable.GetObjectData method and a special constructor that is used when
the source object is deserialized. You use the GetObjectData method to populate the SerializationInfo the data
that is required to serialize the source object at runtime.
The common language runtime calls the constructor during deserialization to construct a replica of the source
object. The constructor takes two parameters, a SerializationInfo type and a
System.Runtime.Serialization.StreamingContext type. The StreamingContext parameter describes the source
and destination of a given serialized stream.
Custom Serialization Example
The following code example demonstrates a custom serialization object that implements the basic functionality
that is required for compliance with the ISerializable interface. In the first procedure of this example, you
create a .NET Framework assembly that includes a serializable type. In the second procedure, in the Business
Central development environment, you create a codeunit that includes two DotNet variables for the serializable
type. You set one variable to target the Business Central Windows client and the other to target the Business
Central Server. In AL code, you add code that transfers the value for the DotNet variable on the Business Central
Server to the Business Central Windows client. You will also add code that verifies that the data transfer is
successful.
To c r e a t e t h e c u st o m se r i a l i z a t i o n o b j e c t

1. In Microsoft Visual Studio, create a C# Class Library project called SerializationSample.


2. Add the following code.
using System;
using System.Runtime.Serialization;

[Serializable]
public class SerializeWithInterface : ISerializable
{
// Defines a field that will not be serialized.
[NonSerialized]
private string notSerializedField;
// Defines two fields that will be serialized.
private int serializedIntField;
private string serializedStringField;
// Specifies literal field names.
private const string serializedIntFieldName = “serializedIntField”;
private const string serializedStringFieldName = “serializeStringField”;

// Defines a default constructor that initializes the object with default values.
public SerializeWithInterface()
{
this.serializedIntField = 1;
this.notSerializedField = string.Empty;
this.serializedStringField = string.Empty;
}

// Defines the protected constructor that is required by the ISerializable interface.


// Data is stored in the SerializationInfo argument and is extracted using the GetValue method.
protected SerializeWithInterface(SerializationInfo si, StreamingContext context)
{
this.serializedStringField = (string)si.GetValue(serializedStringFieldName, typeof(string));
this.serializedIntField = (int)si.GetValue(serializedIntFieldName, typeof(int));
}

// Fills the SerializationInfo object with data that must to be sent to the replicated object.
// Data is stored in the dictionary using the AddValue method.
// The SerializationInfo object is a key/value dictionary.
// The name you use to store the value must match the name used in the constructor.
// For this reason, a string constant is used.
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue(serializedStringFieldName, this.serializedStringField);
info.AddValue(serializedIntFieldName, this.serializedIntField);
}

// Remaining class implementation is irrelevant for the serialization process.


// The SerializedStringField property is used by AL code to verify that the contained data is
transferred between the server and client.
// SerializedStringField gets or sets the internal serialized string field.
public string SerializedStringField
{
get { return this.serializedStringField; }
set { this.serializedStringField = value; }
}
}

3. Build the project.


4. Copy the SerializationSample.dll to the Add-ins folder of the Business Central Windows client and
Business Central Server installation folders.
By default, the path of the Business Central Windows client installation folder is C:\Program Files (x86)\Microsoft
Dynamics 365 Business Central\210\RoleTailored Client\Add-ins.
By default, the path of the Business Central Server installation folder is C:\Program Files\Microsoft Dynamics
365 Business Central\210\Service\Add-ins.
To t e st t h e se r i a l i z a t i o n o b j e c t

1. In the AL Development Environment, add the following code.

dotnet
{
assembly(SerializationSample)
{
type(SerializationSample.SerializeWithInterface; SerializeWithInterface){}
}
}

codeunit 50101 SerializationSample


{
procedure Testing()
var
ServerObject: DotNet SerializeWithInterface;
ClientObject: DotNet SerializeWithInterface;

begin
// Constructor that instantiates the ServerObject object on the server.
ServerObject := ServerObject.SerializeWithInterface();
// Constructor that instantiates the ClientObject object on the server.
ClientObject := ClientObject.SerializeWithInterface();
// Assign unique values to the data members in the two objects.
ServerObject.SerializedStringField := ‘ServerSide’;
ClientObject.SerializedStringField := ‘ClientSide’;
// Transfer the server object to the client object using serialization.
ClientObject := ServerObject;
// Test if the objects contain the same data.
If ClientObject.SerializedStringField <> ServerObject.SerializedStringField then
Error(‘Client object does not match the server object.’);
Message(‘Server data has been serialized to the client object.’);
end;
}

The line that contains assignment of the Ser verObject to the ClientObject causes the serialization process to
run. When completed, the message Ser ver data has been serialized to the client object appears, which
verifies that the server object has been transferred to the client object.

See Also
Get Started with AL
Getting started with Microsoft .NET Interoperability from AL Migrating from .NET Framework to .NET Standard
.NET Control Add-Ins
Subscribing to Events in a .NET Framework Type
Using Designer
AL Language Extension Configuration
The Microsoft_Application.app File
2/6/2023 • 3 minutes to read • Edit Online

The Microsoft_Application.app file is included with Business Central and is located in the
\Applications\Application\Source folder. The Microsoft_Application.app file logically encapsulates all of the
extensions making up a solution, for example, version 16.0.0.0 of the base and system application package
files, and it provides a convenient way to define and refer to this solution identity.

NOTE
In previous versions the references to base and system application were stated explicitly under dependencies in the
app.json file of the extension. Instead you must now use the Application version property in the app.json file. For
more information, see JSON Files.

The file name of the reference is Microsoft_Application.app and in the app.json file of the application package
file, the name is Application . For code-customized base applications that have their own app ID, the
Microsoft_Application.app file can be modified to reference the app ID of the code-customized base
applications instead. This allows any extensions that are dependent on the Application to resolve to the custom
app ID.

NOTE
The partner who redefines the application must ensure that extensions that are dependent on the Application compile
and work. This can be ensured, for example, by not introducing any breaking changes.

IMPORTANT
If you have modified the Microsoft_Application.app file, you can rename the file name, and change information about
the publisher , but it is important to keep "name": "Application" in the extension, which is what is being checked
for in terms of symbols references. It is also important to keep the propagateDependencies set to true . The version
must be set to the version of the Microsoft base application with which it is compatible. The id must be changed to
reference the app ID of the code-customized base application.

Changing the app.json file for a code-customized base application


The app.json file of the Microsoft_Application.app file looks like the following example for Business Central
version 15.3.
{
"id": "c1335042-3002-4257-bf8a-75c898ccb1b8",
"name": "Application",
"publisher": "Microsoft",
"version": "15.3.40074.40254",
"propagateDependencies": true,
"logo": "ExtensionLogo.png",
"privacyStatement": "https://go.microsoft.com/fwlink/?LinkId=724009",
"EULA": "https://go.microsoft.com/fwlink/?linkid=2009120",
"help": "https://go.microsoft.com/fwlink/?linkid=2104024",
"url": "https://go.microsoft.com/fwlink/?LinkId=724011",
"dependencies": [
{
"appId": "437dbf0e-84ff-417a-965d-ed2bb9650972",
"name": "Base Application",
"publisher": "Microsoft",
"version": "15.3.0.0"
},
{
"appId": "63ca2fa4-4f03-4f2b-a480-172fef340d3f",
"name": "System Application",
"publisher": "Microsoft",
"version": "15.3.0.0"
}
],
"screenshots": [

],
"platform": "15.0.0.0",
"showMyCode": true,
"brief": "Application (W1)"
}

If you have a code-customized base application, the file can be edited to reflect the dependency to this instead.
To do so, update the "dependencies": [] section and change the
"appId": "437dbf0e-84ff-417a-965d-ed2bb9650972" to the appId of your code-customized base application. You
can update the "name" and "publisher" information to match too.

...
"dependencies": [
{
"appId": "<appId of the code-customized base app>",
"name": "Customized Base Application",
"publisher": "PartnerSolutions",
"version": "15.3.0.0"
},
...
],
...

Up-taking the Application app


The Application app logically encapsulates apps making up a solution (such as the Base Application and System
Application), and provides an abstraction to protect the AppSource and per-tenant (PTEs) extensions running on
top of that solution from not being able to resolve dependencies to these apps.
When using it, future refactoring of the referenced solution; like extracting some areas into separate apps, or
changes to the identities of the apps which comprise the solution, will not be forcing all other dependent apps to
change or add new apps to their dependencies, as these dependencies will be resolved implicitly via the
reference to the Application app.
Additionally, it is meant to simplify the on-premises upgrade scenarios, when customizations are extracted from
the Base Application into extensions. And finally it makes it possible to make the same apps available not only to
the Business Central customers, but also to the customers of the rich, vertical solutions called Embed Apps,
which are also running in the Business Central service.
To enable these benefits, all you need to do, as an AppSource or PTE app owner, is to add the "application"
property in the app.json file of your app and provide the minimum Microsoft Base Application version that this
app is compatible with. For more information, see JSON Files. Also, you need to remove the direct dependencies
to the Base Application and System Application from the app.json file. See the following example:

{
"id": "e5645aaf-74be-453a-ab50-2e34ec3ee53c",
"name": "Fabrikam Gadgets Management",
"publisher": "Fabrikam",
"version": "15.3.41056.29085",
"logo": "ExtensionLogo.png",
"privacyStatement": "https://go.microsoft.com/fwlink/?LinkId=724009",
"EULA": "https://go.microsoft.com/fwlink/?linkid=2009120",
"help": "https://go.microsoft.com/fwlink/?linkid=2104024",
"url": "https://go.microsoft.com/fwlink/?LinkId=724011",
"application": "15.3.0.0",
"dependencies": [
],
"screenshots": [

],
"platform": "15.0.0.0",
"showMyCode": true,
"brief": "Fabrikam Gadgets Mgt."
}

IMPORTANT
Soon up-taking the Application app will also be a mandatory requirement for AppSource apps, enforced by the
AppSource technical validation. Thus, it is highly recommended to change the existing AppSource apps at first
convenience, for example with your next planned app update, and adopt the "application" property for all new
AppSource apps. We also recommend up-taking the Application app for the customized Base Applications on-premise,
and per-tenant-extensions (PTEs) that you use in the Business Central online environments.

See Also
JSON Files
Install an Update
App Identity
Publishing a Code-Customized Base Application for
Business Central On-Prem
2/6/2023 • 4 minutes to read • Edit Online

APPLIES TO: Business Central 2019 release wave 2 and later

This topic describes the steps and development environment configuration settings that are needed in order to
customize the Base Application code in Dynamics 365 Business Central on-premises and publish the code-
customized Base Application to the local server.

IMPORTANT
Instead of code-customizing the Base Application, it is strongly recommended to create extensions whenever possible.

NOTE
The steps in this topic are not validated against a Docker environment. If you are running the on-premises installation
and development from Docker, there can be dependencies and other steps that you need to take into consideration.

Prerequisites
Make sure to have the following prerequisites installed to be able to follow the steps in this topic.
Dynamics 365 Business Central on-premises with the AL Language Development Environment option
installed
Visual Studio Code
The AL Language extension

To publish a code customization for Business Central on-premises


1. Get the Base Application source from the /Applications/BaseApp/Source folder on the DVD.
2. Unzip the BaseApplication.source.zip file and open the source folder in Visual Studio Code. This folder
contains all of the base application objects and an app.json file with the settings enabled for OnPrem .
3. Now, you must configure your launch.json file settings to the local server. For more information, see
JSON Files.
4. Next, download symbols for the Base Application using Ctrl+Shift+P and then choose Download
Symbols .
5. Customize the Base Application. In this example, we will just modify the text in the Name field on the
Customer Card page to be Strong . So, in the CustomerCard.Page.al file, we specify the following extra
line of code:
...
field(Name; Name)
{
ApplicationArea = All;
Importance = Promoted;
ShowMandatory = true;

Style = Strong; // Show name in bold

ToolTip = 'Specifies the customer''s name. This name will appear on all sales documents for the
customer.';

trigger OnValidate()
begin
CurrPage.SaveRecord;
end;
}
...

6. Use the Business Central Administration Console to ensure that the settings for developing for on-
premises are correctly set. On the Development tab these must be:
Allowed Extension Target Level is set to OnPrem .
Enable Developer Ser vice Endpoint checkbox is selected.
7. In the app.json file, in the dependencies section, make sure that version is set to the version of the
System Application found in the project under .alpackages . For example:

"dependencies": [
{
"appId": "63ca2fa4-4f03-4f2b-a480-172fef340d3f",
"publisher": "Microsoft",
"name": "System Application",
"version": "16.0.10037.0"
}
],

8. Configure User Settings or Workspace Settings to include the following paths for the
"al.assemblyProbingPaths" setting. For more information, see AL Language Extension Configuration.

"al.assemblyProbingPaths": [
"C:\\Program Files\\Microsoft Dynamics 365 Business Central\\170\\Service",
"C:\\Program Files (x86)\\Microsoft Dynamics 365 Business Central\\170",
"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8",
"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\WindowsPowerShell"
],

9. For improved performance when working with a large project like the Base Application, see the Optimize
Visual Studio Code Editing and Building Performance topic.
10. Next, you must uninstall all extensions from the command line. If you at this point try to just publish the
extension from Visual Studio Code you will get the following error:
The request for path /BC170/dev/apps?SchemaUpdateMode=synchronize&DependencyPublishingOption=ignore
failed with code 422. Reason: The extension could not be deployed because it is already deployed on
another tenant.

You get the error because the extensions are installed in the global scope. If you want to publish an
extension from Visual Studio Code, within the developer scope, you will have to first uninstall and then
unpublish the extensions from the command line.
Ideally, you should uninstall the application that you want to update and all its dependencies. To uninstall
the Base Application use the following cmdlet:
Uninstall-NavApp -Name "Base Application" -ServerInstance BC170 -Force

Use the -Force parameter to uninstall all dependencies.

NOTE
Alternatively, uninstall everything using the following cmdlet.
Get-NAVAppInfo -ServerInstance BC170 | %{Uninstall-NAVApp -Name $_.Name -ServerInstance BC170 -
Force}

11. Having uninstalled, the next step is to unpublish the application and all of its dependencies. This needs to
happen before we can publish it. The following command can be used if there are no dependencies to the
Base Application:
Unpublish-NavApp -Name "Base Application" -ServerInstance BC170

But if there are dependencies on the Base Application this will give an error. To solve this, you must
unpublish all the applications with dependencies on the Base Application. This is easier to do using a
script that recursively removes the dependencies. Use Windows PowerShell ISE to create a new script
with the following lines of code:

function UnpublishAppAndDependencies($ServerInstance, $ApplicationName)


{
Get-NAVAppInfo -ServerInstance $ServerInstance | Where-Object {
# If the dependencies of this extension include the application that we want to unpublish, it
means we have to unpublish this application first.
(Get-NavAppInfo -ServerInstance $ServerInstance -Name $_.Name).Dependencies | Where-Object
{$_.Name -eq $ApplicationName}
} | ForEach-Object {
UnpublishAppAndDependencies $ServerInstance $_.Name
}

Unpublish-NavApp -ServerInstance $ServerInstance -Name $ApplicationName


}

function UninstallAndUnpublish($ServerInstance, $ApplicationName)


{
Uninstall-NavApp -ServerInstance $ServerInstance -Name $ApplicationName -Force
UnpublishAppAndDependencies $ServerInstance $ApplicationName

UninstallAndUnpublish -ServerInstance "BC170" -ApplicationName "Base Application"

12. Save the script as unpublish.ps1 .


13. Run the script from the PowerShell commandline to handle the uninstall and unpublishing of the Base
Application and its dependencies: .\unpublish.ps1

NOTE
Use "dependencyPublishingOption": "Ignore" in the launch.json file to only publish this extension. For
more information, see JSON Files.

14. Import a license with rights to publish the extension. For example:
Import-NAVServerLicense -ServerInstance BC -LicenseFile "C:\Users\mylicense.BCLicense"

15. Press Ctrl+F5 to publish the modified Base Application as an extension from Visual Studio Code.
The Base Application is now published with the small customization of bolding the text in the Name field on the
Customer Card page.

See Also
Unpublishing and Uninstalling Extensions
Developing Extensions
Extending Application Areas
2/6/2023 • 5 minutes to read • Edit Online

Application areas represent a feature in the system that offers developers, administrators, and users the ability
to define differentiated user experiences.
Application areas are mapped to controls to show or hide them on page objects to enable more or fewer
business scenarios.

Extending application areas and the experience tier


In this example you will:
Add a new application area in the Application Area Setup table.
Enable the application area in the OnInstallAppPerCompany trigger.
Extend the experience tier in the OnGetExperienceAppArea event.
Modify the experience tier (optional).
Validate the application area in the OnValidateApplicationAreas .

IMPORTANT
The code used in this example is still under active development and might be subject to change in the future.

The following example extends the Customer List page. The field ExampleField is added and it is followed by
a series of properties. The ApplicationArea property sets the application areas that apply to the control and in
this code, ExampleAppArea is assigned to it.

IMPORTANT
If your extension fails to use ApplicationArea in any controls or actions, they will not be visible when you use an
experience tier.

The OnOpenPage trigger will display the message only if ApplicationArea is enabled.
pageextension 50100 CustomerListExt extends "Customer List"
{
layout
{
addafter(Name)
{
field(ExampleField; "Name 2")
{
Caption = 'Example Field';
ApplicationArea = ExampleAppArea;
ToolTip = 'This is a field added by an example extension';
Importance = Promoted;
}
}
}

trigger OnOpenPage()
var
EnableExampleExtension : Codeunit "Enable Example Extension";
begin
if EnableExampleExtension.IsExampleApplicationAreaEnabled() then
Message('App published: Example Extension');
end;
}

Adding an application area


To add an application area, the Application Area Setup table must be extended. A new boolean field is added
and the name of this field will be used in the attribute that you want to be tagged with this application area. This
particular case, in the code below, is an exception, because space is used inside it. Usually, spaces are omitted in
the application area attribute. At this point, the extension has an application area but it still needs to be enabled.

tableextension 50100 "Application Area Setup" extends "Application Area Setup"


{
fields
{
// Spaces in field name are omitted in the ApplicationArea attribute
// e.g. ApplicationArea = ExampleAppArea;
field(50100;"Example App Area";Boolean)
{
}
}
}

The codeunit Install Example Extension is of the subtype Install and it enables the application area inside the
OnInstallAppPerCompany trigger.
codeunit 50101 "Install Example Extension"
{
Subtype = Install;

trigger OnInstallAppPerCompany()
var
EnableApplicationArea : Codeunit "Enable Example Extension";
begin
if(EnableApplicationArea.IsExampleApplicationAreaEnabled()) then
exit;

EnableApplicationArea.EnableExampleExtension();

// Add your code here


end;
}

The registration of the application area inside an experience tier is made inside the
OnGetEssentialExperienceAppArea . There are different versions of this event, one for each experience tier
and in this case, Essential is chosen. This will make the extension visible inside the Essential experience and the
event exposes an Application Area Setup temporary record; TempApplicationAreaSetup , to the
Application Area Setup table. At this point, to enable the application area, this must be set to true.

NOTE
This event is important because it is called every single time an experience tier is reset, which can happen because of
many reasons.

Another thing that is possible inside these methods is to modify the experience tier. You can also modify other
application areas, such as creating an extension that extends the Fixed Assets functionality. By subscribing to
OnValidateApplicationAreas , the application area inside an experience tier is validated.
OnValidateApplicationAreas is guaranteed to be executed after the events in the
OnGet...ExperienceAppArea family. The validation is necessary in the presence of extensions concurrently
manipulating the same application areas.
In case a needed application area is not enabled, the suggested action is to show an error and turn off the
extension to avoid unintended behavior. However, if the functionality controlled by this application area is of
secondary importance and its loss does not affect the rest of the extension, it is also appropriate to keep the
extension enabled.
codeunit 50100 "Enable Example Extension"
{
// Extend and modify Essential experience tier with "Example App Area"
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Application Area Mgmt.",
'OnGetEssentialExperienceAppAreas', '', false, false)]
local procedure RegisterExampleExtensionOnGetEssentialExperienceAppAreas(var TempApplicationAreaSetup:
Record "Application Area Setup" temporary)
begin
TempApplicationAreaSetup."Example App Area" := true;
// Modify other application areas here
end;

// Validate that application areas needed for the extension are enabled
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Application Area Mgmt.", 'OnValidateApplicationAreas',
'', false, false)]
local procedure VerifyApplicationAreasOnValidateApplicationAreas(ExperienceTierSetup: Record "Experience
Tier Setup"; TempApplicationAreaSetup: Record "Application Area Setup" temporary)
begin
if ExperienceTierSetup.Essential then
if not TempApplicationAreaSetup."Example App Area" then
Error('Example App Area should be part of Essential in order for the Example Extension to
work.');
end;

// Helpers ................................................................
procedure IsExampleApplicationAreaEnabled() : Boolean
var
ApplicationAreaSetup: Record "Application Area Setup";
ApplicationAreaMgmtFacade: Codeunit "Application Area Mgmt. Facade";
begin
if ApplicationAreaMgmtFacade.GetApplicationAreaSetupRecFromCompany(ApplicationAreaSetup,
CompanyName()) then
exit(ApplicationAreaSetup."Example App Area");
end;

procedure EnableExampleExtension()
var
ApplicationAreaMgmtFacade: Codeunit "Application Area Mgmt. Facade";
begin
ApplicationAreaMgmtFacade.RefreshExperienceTierCurrentCompany();
end;
}

Adding Advanced application area to the Essentials and Premium


experiences using an extension
If you are familiar with Dynamics NAV you will have noticed that Dynamics 365 Business Central is not exposing
all the controls/actions that you find in Dynamics NAV. These controls have been hidden so far by using the
application area Advanced , which is not assigned to any experiences. For more information, see FAQ.
Most of these fields will become available/visible soon, but until then you will have to create an extension to get
(almost) the same experience as you have in Dynamics NAV. See the example below.

IMPORTANT
Adding the application area Advanced to the experience will mean that you lose some of the simplification made to
pages. For example, you will see more actions duplicated on many pages, compared to Business Central where the
experience is intended to be simpler than in Dynamics NAV. You must also consider that we plan to re-tag the Advanced
actions/controls and add them to the Essentials and/or Premium experiences in a future release.

To enable Advanced in an extension


Depending on which experience you want to enable Advanced for you can subscribe to
OnGetEssentialExperienceAppAreas or OnGetPremiumExperienceAppAreas . If you have defined your own experience
you must subscribe to OnSetExperienceTier .
The experiences are additive so you only need to subscribe to one of the events. For example, to enable
Essentials and Premium experiences you only need to subscribe to OnGetEssentialExperienceAppAreas .

codeunit 50102 EnableAdvancedApplicationArea


{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Application Area Mgmt. Facade",
'OnGetEssentialExperienceAppAreas', '', false, false)]
local procedure EnableAdvancedApplicationAreaOnGetEssentialExperienceAppAreas(var
TempApplicationAreaSetup: Record "Application Area Setup" temporary)
begin
TempApplicationAreaSetup.Advanced := true;
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Application Area Mgmt. Facade",


'OnGetPremiumExperienceAppAreas', '', false, false)]
local procedure EnableAdvancedApplicationAreaOnGetPremiumExperienceAppAreas(var
TempApplicationAreaSetup: Record "Application Area Setup" temporary)
begin
TempApplicationAreaSetup.Advanced := true;
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Application Area Mgmt. Facade", 'OnSetExperienceTier',


'', false, false)]
local procedure EnableAdvancedApplicationAreaOnSetExperienceTier(ExperienceTierSetup: Record "Experience
Tier Setup"; var TempApplicationAreaSetup: Record "Application Area Setup" temporary; var
ApplicationAreasSet: Boolean)
begin
TempApplicationAreaSetup.Advanced := true;
end;
}

Application areas advantages and disadvantages


If you decide to code application areas as an extension, there are some aspects that must be considered.
Application areas enable hiding entire business scenarios and you can have the same code base, which makes it
possible to quickly modify the UI for different business scenarios or audiences. However, tagging errors as
missing tags or incorrect tags will occur and every single control will need to be tagged.

See Also
ApplicationArea Property
ApplicationArea Method
AccessByPermission Property
Properties
Extending Item Charge Distribution Methods
2/6/2023 • 5 minutes to read • Edit Online

To ensure correct valuation, your inventory items must carry any added costs, such as freight, physical handling,
insurance, and transportation that you incur when purchasing or selling the items.
Users can add these costs by adding a Charge (Item) line to the involved purchase or sales document. For more
information, see Use Item Charges to Account for Additional Trade Costs in application help.
Item charges are distributed over other item lines in the document according to a distribution method.
Dynamics 365 Business Central offers four distribution methods out of the box: Equally , By Amount , By
Weight , and By Volume . This article explains how to remove or add item charge distribution methods. The
article describes the method for purchases. The steps are similar for sales, except the events are located in
codeunit 5807, Item Charge Assgnt. (Sales) .
To enable extension of item charges distribution methods, two events can be found in codeunit 5805, Item
Charge Assgnt. (Purch.) . The work consists of the following two tasks:
1. In the OnBeforeShowSuggestItemChargeAssignStrMenu event, you manipulate the options that are
presented to users. You can remove, add, and change the order of the options.
Keep in mind that other extensions may also manipulate the options.
You should not assume that an option will exist, nor should you write code that may remove an option
added by another extension.
2. In the OnAssignItemCharges event, you distribute the item charge amount over the item lines
according to your new distribution method.
You must verify that the option selected by the user is your new option. If it is not, then exit without
taking action.
When you have distributed the amount over the lines, you must set the ItemChargesAssigned boolean
to true. If you do not set this boolean to true, an error will occur.
The following procedures show how to extend the item charges distribution methods:
1. Add a new option to the item charges distribution methods in the
OnBeforeShowSuggestItemChargeAssignStrMenu event.
2. Add a new distribution method for item charges.
3. Call the new distribution method in the OnAssignItemCharges event.
The procedures are based on an example where the By Fair y Dust option is added to the string menu
(STRMENU) and added to the CASE statement.

NOTE
To complete this example you will have to add a new field Fair y Dust to the Purchase Line table and other relevant
tables and pages.

To add a new option to the item charges distribution methods


Create a new codeunit and add an event subscriber to the
OnBeforeShowSuggestItemChargeAssignStrMenu event.
codeunit 50100 "Item Ch. Assign by Fairy Dust"
{
var
ByFairyDustTok: Label 'By Fairy Dust';

local procedure AssignByFairyDustMenuText(): Text


begin
exit(ByFairyDustTok)
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Item Charge Assgnt. (Purch.)",


'OnBeforeShowSuggestItemChargeAssignStrMenu', '', false, false)]
local procedure AddByFairyDustOnBeforeShowSuggestItemChargeAssignStrMenu(PurchLine: Record "Purchase
Line"; var SuggestItemChargeMenuTxt: Text; var SuggestItemChargeMessageTxt: Text; var Selection: Integer)
begin
// if 'By Fairy Dust' is not in the menu options, add it at the end
if StrPos(SuggestItemChargeMenuTxt, AssignByFairyDustMenuText) = 0 then begin
SuggestItemChargeMenuTxt += ',' + AssignByFairyDustMenuText;
// make the last option ('By Fairy Dust') the default selection
Selection := StrLen(DelChr(SuggestItemChargeMenuTxt, '=', DelChr(SuggestItemChargeMenuTxt, '=',
','))) + 1;
end;
end;
}

To add a new distribution method for item charges


In the new codeunit, add functions to distribute the charges over the item lines.

local procedure AssignByFairyDust(var ItemChargeAssignmentPurch: Record "Item Charge Assignment


(Purch)"; Currency: Record Currency; TotalQtyToAssign: Decimal; TotalAmtToAssign: Decimal);
var
TempItemChargeAssgntPurch: Record "Item Charge Assignment (Purch)" temporary;
LineArray: array[2] OF Decimal;
TotalFairyDust: Decimal;
QtyRemaining: Decimal;
AmountRemaining: Decimal;
begin
// copy lines to temp variable and calculate total Fairy Dust
repeat
if not ItemChargeAssignmentPurch.PurchLineInvoiced then begin
TempItemChargeAssgntPurch.Init();
TempItemChargeAssgntPurch := ItemChargeAssignmentPurch;
TempItemChargeAssgntPurch.Insert(false);
GetItemValues(TempItemChargeAssgntPurch, LineArray);
TotalFairyDust += (LineArray[2] * LineArray[1]);
end;
until ItemChargeAssignmentPurch.Next = 0;

if TempItemChargeAssgntPurch.Findset(true) then
repeat
// Calculate Fairy Dust to assign to the line
GetItemValues(TempItemChargeAssgntPurch, LineArray);
if TotalFairyDust <> 0 then
TempItemChargeAssgntPurch."Qty. to Assign" :=
(TotalQtyToAssign * LineArray[2] * LineArray[1]) / TotalFairyDust + QtyRemaining
else
TempItemChargeAssgntPurch."Qty. to Assign" := 0;

// Assign Fairy Dust to the line and calculate the remaining Fairy Dust to assign
ItemChargeAssignmentPurch.Get(
TempItemChargeAssgntPurch."Document Type",
TempItemChargeAssgntPurch."Document No.",
TempItemChargeAssgntPurch."Document Line No.",
TempItemChargeAssgntPurch."Line No.");
ItemChargeAssignmentPurch."Qty. to Assign" := Round(TempItemChargeAssgntPurch."Qty. to
Assign", 0.00001);
ItemChargeAssignmentPurch."Amount to Assign" :=
ItemChargeAssignmentPurch."Qty. to Assign" * ItemChargeAssignmentPurch."Unit Cost" +
AmountRemaining;
AmountRemaining := ItemChargeAssignmentPurch."Amount to Assign" -
Round(ItemChargeAssignmentPurch."Amount to Assign", Currency."Amount Rounding Precision");
QtyRemaining := TempItemChargeAssgntPurch."Qty. to Assign" - ItemChargeAssignmentPurch."Qty.
to Assign";
ItemChargeAssignmentPurch."Amount to Assign" :=
Round(ItemChargeAssignmentPurch."Amount to Assign", Currency."Amount Rounding Precision");
ItemChargeAssignmentPurch.Modify(false);

until TempItemChargeAssgntPurch.Next = 0;
TempItemChargeAssgntPurch.DeleteAll(false);
end;

procedure GetItemValues(TempItemChargeAssgntPurch: Record "Item Charge Assignment (Purch)" temporary;


var DecimalArray: Array[2] OF Decimal);
var
PurchaseLine: Record "Purchase Line";
PurchRcptLine: Record "Purch. Rcpt. Line";
ReturnShptLine: Record "Return Shipment Line";
TransferRcptLine: Record "Transfer Receipt Line";
SalesShptLine: Record "Sales Shipment Line";
ReturnRcptLine: Record "Return Receipt Line";
begin
// Get the Fairy Dust for the line
Clear(DecimalArray);
with TempItemChargeAssgntPurch do
case "Applies-to Doc. Type" of
"Applies-to Doc. Type"::Order,
"Applies-to Doc. Type"::Invoice,
"Applies-to Doc. Type"::"Return Order",
"Applies-to Doc. Type"::"Credit Memo":
begin
PurchaseLine.Get("Applies-to Doc. Type", "Applies-to Doc. No.", "Applies-to Doc.
Line No.");
DecimalArray[1] := PurchaseLine.Quantity;
DecimalArray[2] := PurchaseLine."Fairy Dust";
end;
"Applies-to Doc. Type"::Receipt:
begin
PurchRcptLine.Get("Applies-to Doc. No.", "Applies-to Doc. Line No.");
DecimalArray[1] := PurchRcptLine.Quantity;
DecimalArray[2] := PurchRcptLine."Fairy Dust";
end;

"Applies-to Doc. Type"::"Return Receipt":


begin
ReturnRcptLine.Get("Applies-to Doc. No.", "Applies-to Doc. Line No.");
DecimalArray[1] := ReturnRcptLine.Quantity;
DecimalArray[2] := ReturnRcptLine."Fairy Dust";
end;
"Applies-to Doc. Type"::"Return Shipment":
begin
ReturnShptLine.Get("Applies-to Doc. No.", "Applies-to Doc. Line No.");
DecimalArray[1] := ReturnShptLine.Quantity;
DecimalArray[2] := ReturnShptLine."Fairy Dust";
end;
"Applies-to Doc. Type"::"Transfer Receipt":
begin
TransferRcptLine.Get("Applies-to Doc. No.", "Applies-to Doc. Line No.");
DecimalArray[1] := TransferRcptLine.Quantity;
DecimalArray[2] := TransferRcptLine."Fairy Dust";
end;
"Applies-to Doc. Type"::"Sales Shipment":
begin
SalesShptLine.Get("Applies-to Doc. No.", "Applies-to Doc. Line No.");
SalesShptLine.Get("Applies-to Doc. No.", "Applies-to Doc. Line No.");
DecimalArray[1] := SalesShptLine.Quantity;
DecimalArray[2] := SalesShptLine."Fairy Dust";
end;
end;
end;

To call the new distribution method


In the new codeunit, add a subscriber to the OnAssignItemCharges event.

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Item Charge Assgnt. (Purch.)", 'OnAssignItemCharges',


'', false, false)]
local procedure AssignByFairyDustOnAssignItemCharges(SelectionTxt: Text; var ItemChargeAssignmentPurch:
Record "Item Charge Assignment (Purch)"; Currency: Record Currency; PurchaseHeader: Record "Purchase
Header"; TotalQtyToAssign: Decimal; TotalAmtToAssign: Decimal; VAR ItemChargesAssigned: Boolean);
begin
// if item charges are already assigned, exit
if ItemChargesAssigned then
exit;
// if the user did not choose 'By Fairy Dust', exit
if not (SelectionTxt = AssignByFairyDustMenuText) then
exit;
// assign item charges by fairy dust
AssignByFairyDust(ItemChargeAssignmentPurch, Currency, TotalQtyToAssign, TotalAmtToAssign);
// charges have been assigned
ItemChargesAssigned := true;
end;

See Also
Extending Application Areas
Extending Price Calculations
2/6/2023 • 24 minutes to read • Edit Online

If you offer special prices and line discounts for sales and purchases, Dynamics 365 Business Central can
automatically calculate prices on sales and purchase documents, and on job and item journal lines. The price is
the lowest permissible price with the highest permissible line discount on a given date. Dynamics 365 Business
Central automatically calculates the price when it inserts the unit price and the line discount percentage for
items on new document and journal lines. For more information, see Price Calculation.
This topic describes how price calculations are implemented in 2020 release wave 1 (referred to as "Business
Central Version 16" in the illustrations), and provides comparisons with 2019 release wave 2 (referred to as
Business Central Version 15 in the illustrations) to show what we have changed. It also provides some examples
of how you can extend price calculations in 2020 release wave 1 and later.

Price Calculation Setup


Price calculations are based on the Price Calculation Setup table, where you can choose an existing
implementation, as shown in the following image.

The Price Calculation Setup table has the Code field as its primary key. The value of the field is calculated by
combining the values in the Method, Type, Product Type, and Implementation fields. For example, it is [1-1-0]-
7003 for the setup line when the following fields contain the following values:
Method contains Lowest Price
Type contains Sale
Product Type contains All
Implementation contains Business Central (Version 15.0)
You can have multiple setups with the same combination of method, type, and product type. The
implementation should always be different though, because each implementation provides different
calculations. The default implementation is defined by the Default field. For example, in 2020 release wave 1
the following setups are available:

M ET H O D TYPE P RO DUC T T Y P E IM P L EM EN TAT IO N DEFA ULT

Lowest Price Sale All Business Central X


(Version 15.0)

Lowest Price Sale All Business Central


(Version 16.0)

By default, all sales lines use the Business Central (Version 15.0) implementation to calculate prices, unless the
second line has a detailed setup that defines exceptions.
The Price Calculation method on the document line searches for a setup that that has a matching combination of
the method, the price type, and product type on the document line. The method then searches for detailed lines
that contain exceptions for the combination of a source group (Customer, Vendor, and Job) and an product (item,
resource, and so on) on the document line. If a matching setup is found its implementation is used to calculate a
price. If there is no matching setup exception, we use the default implementation.
For example, let's say we have a line on a sales order for Customer 20000 contains item 1000. The default
implementation for the sale of any asset is Business Central (Version 15.0), but the Business Central (Version
16.0) implementation contains a detailed setup line for Item 1000. That means that the Business Central (Version
16.0) implementation will calculate the price.
You can enter detailed setup records for non-default setup lines. The following image shows the relation
between a setup line and a detailed setup.

For a Business Central (Version 15.0) implementation, you can only edit the Default field. The records are
inserted by the codeunits that subscribe to the OnFindSupportedSetup() event in the Price Calculation Mgt.
codeunit. The two price calculation implementation codeunits add pairs of such records, one for the sale of
products and another for purchases.
Because the Price Calculation Setup table is extensible, you can add new fields to the key by subscribing to the
OnAfterDefineCode() event.
Each codeunit that implements the Price Calculation interface must subscribe to the OnFindSupportedSetup()
event of the Price Calculation Mgt codeunit to fill the price calculation setup table with new options.
Price Type
The Type field is an extensible Price Type enum that contains the following values:
Any (0)
Sale (1)
Purchase (2)
The values are part of the composite key in the Price Calculation Setup table. Sales and service lines use the Sale
type, purchase lines use the Purchase type, and job or item journal lines use both for calculating price and cost.
The Any value is the default value, and is used when a line contains both a price and a cost.
Product Type
The Product Type field is an extensible Price Asset Type enum that contains the following values:
All (0)
Item (10)
Item Discount Group (20)
Resource (30)
Resource Group (40)
Service Cost (50)
G/L Account (60)
The value in the Product Type field is part of the composite key in the Price Calculation Setup table. If the only
setup record contains Product Type - All , special price calculation implementations per product type are not
needed. The default implementation will be used regardless of the product type in the document line. If you
need different implementations, you must add a setup line with another product type. For example, the
following table shows a Resource Pricing implementation with a resource asset type.

M ET H O D TYPE P RO DUC T T Y P E IM P L EM EN TAT IO N DEFA ULT

Lowest Price Sale All Business Central X


(Version 15.0)

Lowest Price Sale Resource Resource Pricing X

Because only one record has the combination of Lowest Price, Sale, and Resource it will be the default. If a sales
line sells a resource, its price will be calculated by the Resource Pricing implementation. All other products will
use the Business Central (Version 15.0) implementation.
Price Calculation Method
The Method field is an extensible Price Calculation Method enum that contains the following values:
Not defined (0)
Lowest Price (1)
The method value is part of the composite key in the Price Calculation Setup table. A sales document line
inherits the method value from the sales header, which in turn inherits it from one of the following, depending
on where it's defined:
Customer
Customer price group
Sales & Receivable Setup table
The Sales & Receivable Setup table defines the default method, Lowest Price, for all sales prices. If you want to
use a different method, you can specify it on a customer price group or a customer. You cannot edit the method
on sales document headers or lines.

The Purchase & Payables Setup table also defines the default method for all purchase prices. You can redefine it
for a certain vendor. You cannot edit the method on purchase document headers or lines.

Data Structure Comparison


The Business Central (Version 15.0) calculation uses the following tables that store information about prices,
costs, and discounts:
table7002"SalesPrice"
table7004"SalesLineDiscount"
table7012"PurchasePrice"
table7014"PurchaseLineDiscount"
table201"ResourcePrice"
table1014"JobG/LAccountPrice"
table1013"JobItemPrice"
table1012"JobResourcePrice"
The Business Central (Version 16.0) calculation uses the following table:
table7001"PriceListLine"
Table7001"PriceListLine" is compatible with all tables used by the Business Central (Version 15.0) calculation. It
contains the set of CopyFrom() methods that convert the data from the tables to the Price List Line table.
If you extended the Business Central (Version 15.0) tables, you must also extend the Price List Line table and the
CopyFrom() methods by subscribing to special events. The following example extends the Sales Price table with
a Document No. field.

tableextension 50010 "Document No in Sales Price" extends "Sales Price"


{
fields
{
field(50000; "Document No."; Code[20])
{ }
}
}

Now we'll extend the Price List Line table with the same field.

tableextension 50011 "Doc. No in Price List Line" extends "Price List Line"
{
fields
{
field(50000; "Document No."; Code[20])
{ }
}
}

Now we'll subscribe to the 'OnCopyFromSalesPrice' event to copy data from "Sales Price" to "Price List Line"
table.

codeunit 50012 "Copy DocumentNo to Price List"


{
[EventSubscriber(ObjectType::Codeunit, Codeunit::CopyFromToPriceListLine, 'OnCopyFromSalesPrice', '',
false, false)]
procedure CopyFromSalesPriceHandler(var SalesPrice: Record "Sales Price"; var PriceListLine: Record
"Price List Line");
begin
PriceListLine."Document No." := SalesPrice."Document No.";
end;
}
The Price Calculation Method field is added to all tables that need calculated prices and discounts:
table 37 "Sales Line"
table 5902 "Service Line"
table 39 "Purchase Line"
table 246 "Requisition Line"
table 83 "Item Journal Line"
table 753 "Standard Item Journal Line"
table 210 "Job Journal Line"
table 1003 "Job Planning Line"
The following image shows the schema of how the methods called in the Sales Line table get the price and
discount amounts from either the Sales Price or Price List Line tables.

Interface Objects
AL interface objects are important for extensibility. They define the capabilities that are available to an object,
and allow implementations to differ as long as they comply with the interface requirements. For more
information, see Interfaces in AL.
Price calculation uses the following AL interface objects:
Price Calculation
Line With Price
Price Source Group
Price Source
Price Calculation
The Price Calculation interface defines methods that calculate amounts and discount percentages on journal and
document lines.
In Business Central (Version 15.0) and earlier, the Price Calculation – V15 interface implementation calls the
Sales Price Calc. Mgt. and Purch. Price Calc. Mgt. codeunits to calculate prices. In Business Central (Version 15.0),
the implementation codeunit is Price Calculation – V16. This codeunit works the same as "Price Calculation –
V15" but is based on a different price line table and makes it easier to extend price calculations.
The Price Calculation - Undefined implementation is used when the setup line does not contain a match for the
document line. This implementation will display a message that states the combination that is missing.

You can add a new implementation codeunit or reuse one as a starting point and rewrite it as needed. For the
new codeunit, you must extend the Price Calculation Handler enum that implements Price Calculation interface
and is used in the Price Calculation Setup table.

enumextension 50000 "SpecialPriceHandler" extends "Price Calculation Handler"


{
value(50000; "Special Price")
{
Implementation = "Price Calculation" = "Price Calc. - Special Price";
}
}

Afterwards you can insert a record in the Price Calculation Setup table and set the new implementation as the
default.
The following code in codeunit 7001 "Price Calculation Mgt." returns a Price Calculation interface that initialized
with the instance of the Line With Price interface that depends on the setup record:
procedure GetHandler(
LineWithPrice: Interface "Line With Price";
var PriceCalculation: Interface "Price Calculation") Result: Boolean;
var
PriceCalculationSetup: Record "Price Calculation Setup";
begin
Result := FindSetup(LineWithPrice, PriceCalculationSetup);
PriceCalculation := PriceCalculationSetup.Implementation;
PriceCalculation.Init(LineWithPrice, PriceCalculationSetup);
end;

After the price calculation implementation is defined, the document line typically calls the methods in the
interface that calculate the price and discount. The following code is used in the Sales Line table:

var
Line: Variant;
begin
PriceCalculation.ApplyDiscount();
PriceCalculation.ApplyPrice(CalledByFieldNo);
PriceCalculation.GetLine(Line);
Rec := Line;
end;

Line With Price


The Line With Price interface defines methods for lines that require the calculation of a price, cost, and line
discount. The following image shows the codeunits that implement this interface.

The following example shows a typical use of the codeunits in the Sales Line table.
var
PriceCalculationMgt: codeunit "Price Calculation Mgt.";
PriceCalculation: Interface "Price Calculation";
SalesLinePrice: Codeunit "Sales Line - Price";
PriceType: Enum "Price Type";
begin
SalesLinePrice.SetLine(PriceType::Sale, SalesHeader, Rec);
PriceCalculationMgt.GetHandler(SalesLinePrice, PriceCalculation);
end;

The SalesLinePrice codeunit is declared directly in the context of the sales line. The instance is initialized by the
interface's SetLine() method, and then passed to the GetHandler() method for PriceCalculation initialization
because all Price Calculation implementation codeunits include an instance of the Line With Price interface,
which stores data about document and journal lines. The following example shows how to declare the interface
variable.

var
CurrLineWithPrice: Interface "Line With Price";

Price Source Group


The Price Source Group interface defines methods for a generic price source group. The Price Source Group
enum defines the list of supported source groups, as follows:
All (0)
Customer (11)
Vendor (21)
Job (31)
This enum is the subset of the Price Source Type enum. Both enums implement the Price Source Group
interface. The interface helps to link the Price Source Type enum with the Sale Price Source Type, Purchase Price
Source Type, and Job Price Source Type enums.

Price Source
The Price Source interface defines methods for price sources, such as vendors or customers. The list of
supported sources is defined by the Price Source Type enum. The interface is used in the Price Source table to
validate the primary key fields and look up respective tables, as shown in the following table.

Example
The Price Source enum implements the Price Source interface and defines Price Source - Customer as the
implementation for the value Customer.

enum 7003 "Price Source Type" implements "Price Source", "Price Source Group"
value(11; Customer)
{
Implementation = "Price Source" = "Price Source - Customer",
"Price Source Group" = "Price Source Group - Customer";
}

The Price Source table has a public method LookupNo() that opens a different page depending on the Source
Type value. The PriceSourceInterface variable gets the implementation value from the Source Type enum value
and then calls the interface's IsLookupOK(Rec) method.

table 7005 "Price Source"


var
PriceSourceInterface: Interface "Price Source";

procedure LookupNo() Result: Boolean;


begin
PriceSourceInterface := "Source Type";
Result := PriceSourceInterface.IsLookupOK(Rec);
end;

Because the source type Customer implementation is the "Price Source - Customer" codeunit, the interface calls
its IsLookupOK() method and then opens the Customer List page.
codeunit 7032 "Price Source - Customer" implements "Price Source"

procedure IsLookupOK(var PriceSource: Record "Price Source"): Boolean


begin
if Customer.Get(PriceSource."Source No.") then;
if Page.RunModal(Page::"Customer List", Customer) = ACTION::LookupOK then begin
PriceSource.Validate("Source No.", Customer."No.");
exit(true);
end;
end;

Examples of Extended Price Calculations


You can extend price calculations, for example, to include other sources or use calculations that allow for
combinations and dependencies. The following sections provide examples.
Example: Change an Item Price When Combined with Another Item
Let's say we want to make the price of one item depend on whether it's sold individually or bundled with one or
more other items. We'll use software licenses in this example.

NOTE
The prices, names, and combinations in this example are completely fictional and intended only to support the scenario
described here. They do not reflect anything in the real-world.

We have the following licenses in our price list. If you buy 70061 or 70062 alone their prices do not change.
However, let's say that we want to offer discounts when one license is purchased along with another. For
example, we want to sell 70064 at a reduced monthly rate when it's purchased in combination with 70061 or
70062. Our list would then look like this.

M O N T H LY B A SE P RIC E P ER
A SSET N UM B ER NAME USER B UN DL E P RIC E

70061 BC Premium $100 N/A

70062 BC Essentials $75 N/A

70063 BC Team Member $8 N/A

70064 Sales Professional $65 $15 and $16 when bundled


with 70061 or 70062.

70065 Customer Service Pro $50 $20 and $21 when bundled
with 70061 or 70062.

The following image shows an example of a Sales Line page that is extended with the Attached to Line No. field.
Notice that the prices are changed based on the combinations of licenses.
Let's look at some sample extensions that will implement this logic for us.
The first table extension adds a new field named Attach to Line No. to the Sales Line table and recalculates
pricing when we make a change. This field will let us create the combinations that determine our discounts. It
also copies the GetPriceCalculationHandler() function from the Sales Line table.

tableextension 50001 "Attach Price" extends "Sales Line"


{
fields
{
field(50001; "Attach To Line No."; Integer)
{
trigger OnValidate()
var
PriceCalculation: Interface "Price Calculation";
begin
GetPriceCalculationHandler(PriceCalculation);
ApplyPrice(FieldNo("Attach To Line No."), PriceCalculation);
end;
}
}

local procedure GetPriceCalculationHandler(var PriceCalculation: Interface "Price Calculation")


var
SalesHeader: Record "Sales Header";
PriceCalculationMgt: codeunit "Price Calculation Mgt.";
SalesLinePrice: Codeunit "Sales Line - Price";
PriceType: Enum "Price Type";
begin
SalesHeader.Get("Document Type", "Document No.");
SalesLinePrice.SetLine(PriceType::Sale, SalesHeader, Rec);
PriceCalculationMgt.GetHandler(SalesLinePrice, PriceCalculation);
end;
}

The following page extension adds the Attach Line No. field to the Sales order page (subform).

pageextension 50001 "Attach Price" extends "Sales Order Subform"


{
layout
{
addAfter(Quantity)
{
field("Attach To Line No."; "Attach To Line No.")
{
ApplicationArea = Basic, Suite;
}
}
}
}
The following table extension adds the Attach to Item No. field to the "Price List line" table.

tableextension 50002 "Attach To Price - Line" extends "Price List Line"


{
fields
{
field(50001; "Attach To Item No."; Code[20])
{
}
}
}

The following table extension adds the Attach to Item No. field to the "Price Calculation Buffer" table.

tableextension 50003 "Attach To Price - Buffer" extends "Price Calculation Buffer"


{
fields
{
field(50001; "Attach To Item No."; Code[20])
{
}
}
}

The calculation that links these three new fields is based on the following events:
OnAfterSetFilters() – Sets the filter on the price list line when searching for the price.
OnAfterFillBuffer() – Copies the value from the sales line to the buffer.
FindItemToAttachToInLine() - Defines the value of the item number stored in the sales line that we attach to.

codeunit 50004 "Attached Price Mgt."


{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Price Calculation Buffer Mgt.", 'OnAfterSetFilters',
'', false, false)]
procedure OnAfterSetFilters(var PriceListLine: Record "Price List Line"; AmountType: Enum "Price Amount
Type"; var PriceCalculationBuffer: Record "Price Calculation Buffer"; ShowAll: Boolean);
begin
PriceListLine.SetRange("Attach To Item No.", PriceCalculationBuffer."Attach To Item No.");
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Sales Line - Price", 'OnAfterFillBuffer', '', false,


false)]
procedure OnAfterFillBuffer(var PriceCalculationBuffer: Record "Price Calculation Buffer"; SalesHeader:
Record "Sales Header"; SalesLine: Record "Sales Line");
begin
PriceCalculationBuffer."Attach To Item No." := FindItemToAttachToInLine(SalesLine);
end;

local procedure FindItemToAttachToInLine(CurrSalesLine: Record "Sales Line"): Code[20]


var
SalesLine: Record "Sales Line";
begin
if SalesLine.Get(CurrSalesLine."Document Type", CurrSalesLine."Document No.", CurrSalesLine."Attach
To Line No.") then
exit(SalesLine."No.");
end;
}

The new price calculation capabilities are not available in the user interface. When a page does become
available, either, from Microsoft or one that you develop yourself, you can use the following sample code to
extend the page with a new control.

field("Attach To Item No."; "Attach To Item No.")


{ }

Example: Add Fixed Assets as a Product Type


This example shows how to add a new type of asset so that it can be used in price calculations for sales and
purchases.
The product type that is set for the price list line is implemented by the Price Asset Type enum. Extend the
enum with a new value, Fixed Asset .

enumextension 50000 "Fixed Asset Type" extends "Price Asset Type"


{
value(5600; "Fixed Asset")
{
Caption = 'Fixed Asset';
Implementation = "Price Asset" = "Price Asset - Fixed Asset";
}
}

The Price Asset Type enum implements the Price Asset interface. Add a Price Asset - Fixed Asset codeunit
that will implement this interface for the Fixed Asset value. Some of the interface's methods are not relevant for
fixed assets, so we will leave them empty but implement the methods from the codeunit. For an example, see
the Price Asset - G/L Account codeunit. The following example will enable the Fixed Asset product type in
price list lines.

- GetNo(),
- GetId(),
- IsLookupOk(),
- IsAssetNoRequired(),
- FilterPriceLines(),
- FillFromBuffer(),
- FillAdditionalFields()

codeunit 50002 "Price Asset - Fixed Asset" implements "Price Asset"


{
var
FixedAsset: Record "Fixed Asset";

procedure GetNo(var PriceAsset: Record "Price Asset")


begin
PriceAsset."Table Id" := Database::"Fixed Asset";
if FixedAsset.GetBySystemId(PriceAsset."Asset ID") then begin
PriceAsset."Asset No." := FixedAsset."No.";
FillAdditionalFields(PriceAsset);
end else
PriceAsset.InitAsset();
end;

procedure GetId(var PriceAsset: Record "Price Asset")


begin
PriceAsset."Table Id" := Database::"Fixed Asset";
if FixedAsset.Get(PriceAsset."Asset No.") then begin
PriceAsset."Asset ID" := FixedAsset.SystemId;
FillAdditionalFields(PriceAsset);
end else
PriceAsset.InitAsset();
end;
procedure IsLookupOK(var PriceAsset: Record "Price Asset"): Boolean
var
xPriceAsset: Record "Price Asset";
begin
xPriceAsset := PriceAsset;
if FixedAsset.Get(xPriceAsset."Asset No.") then;
if Page.RunModal(Page::"Fixed Asset List", FixedAsset) = ACTION::LookupOK then begin
xPriceAsset.Validate("Asset No.", FixedAsset."No.");
PriceAsset := xPriceAsset;
exit(true);
end;
end;

procedure ValidateUnitOfMeasure(var PriceAsset: Record "Price Asset"): Boolean


begin
end;

procedure IsLookupUnitOfMeasureOK(var PriceAsset: Record "Price Asset"): Boolean


begin
end;

procedure IsLookupVariantOK(var PriceAsset: Record "Price Asset"): Boolean


begin
exit(false)
end;

procedure IsAssetNoRequired(): Boolean;


begin
exit(true)
end;

procedure FillBestLine(PriceCalculationBuffer: Record "Price Calculation Buffer"; AmountType: Enum


"Price Amount Type"; var PriceListLine: Record "Price List Line")
begin
end;

procedure FilterPriceLines(PriceAsset: Record "Price Asset"; var PriceListLine: Record "Price List
Line") Result: Boolean;
begin
PriceListLine.SetRange("Asset Type", PriceAsset."Asset Type");
PriceListLine.SetRange("Asset No.", PriceAsset."Asset No.");
end;

procedure PutRelatedAssetsToList(PriceAsset: Record "Price Asset"; var PriceAssetList: Codeunit "Price


Asset List")
begin
end;

procedure FillFromBuffer(var PriceAsset: Record "Price Asset"; PriceCalculationBuffer: Record "Price


Calculation Buffer")
begin
PriceAsset.NewEntry(PriceCalculationBuffer."Asset Type", PriceAsset.Level);
PriceAsset.Validate("Asset No.", PriceCalculationBuffer."Asset No.");
end;
local procedure FillAdditionalFields(var PriceAsset: Record "Price Asset")
begin
PriceAsset.Description := FixedAsset.Description;
PriceAsset."Unit of Measure Code" := '';
PriceAsset."Variant Code" := '';
end;
}

Now lets include this new product type in price calculations.


The Sales Line table provides the OnBeforeUpdateUnitPrice event. This is where we'll add a call that runs
the calculation, because it does not happen for fixed assets in the sales line. See the method
UpdateUnitPriceByField() below, that is the simplified version of the method UpdateUnitPriceByField() that
runs the price calculation in the Sales Line table.
Codeunit "Sales Line - Price" provides the OnAfterGetAssetType event that must return a Price Asset Type
value to be included in price calculations. If the sales line type is Fixed Asset, we return the Fixed Asset
product type.
The following codeunit shows a sample implementation.

codeunit 50001 "Fixed Asset Price Calc."


{
[EventSubscriber(ObjectType::Table, Database::"Sales Line", 'OnBeforeUpdateUnitPrice', '', false,
false)]
local procedure OnBeforeUpdateUnitPrice(var SalesLine: Record "Sales Line"; xSalesLine: Record "Sales
Line"; CalledByFieldNo: Integer; CurrFieldNo: Integer; var Handled: Boolean);
begin
if SalesLine.Type = SalesLine.Type::"Fixed Asset" then begin
UpdateUnitPriceByField(SalesLine, xSalesLine, CalledByFieldNo, CurrFieldNo);
Handled := true;
end;
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Sales Line - Price", 'OnAfterGetAssetType', '', false,


false)]
local procedure OnAfterGetAssetType(SalesLine: Record "Sales Line"; var AssetType: Enum "Price Asset
Type");
begin
if SalesLine.Type = SalesLine.Type::"Fixed Asset" then
AssetType := AssetType::"Fixed Asset";
end;

local procedure UpdateUnitPriceByField(var SalesLine: Record "Sales Line"; xSalesLine: Record "Sales
Line"; CalledByFieldNo: Integer; CurrFieldNo: Integer)
var
SalesHeader: Record "Sales Header";
PriceCalculation: Interface "Price Calculation";
begin
SalesHeader.Get(SalesLine."Document Type", SalesLine."Document No.");
SalesLine.TestField("Qty. per Unit of Measure");

SalesLine.GetPriceCalculationHandler("Price Type"::Sale, SalesHeader, PriceCalculation);


if not (SalesLine."Copied From Posted Doc." and SalesLine.IsCreditDocType()) then begin
PriceCalculation.ApplyDiscount();
SalesLine.ApplyPrice(CalledByFieldNo, PriceCalculation);
end;
SalesLine.Validate("Unit Price");

SalesLine.ClearFieldCausedPriceCalculation();
end;
}

Now we can test the price calculation. In Dynamics 365 Business Central, open the Sales Price List and add a
price line for the product with a minimum quantity of 0, and one with 5.
If we create a sales order with lines for the minimum quantities of the product, the unit prices are calculated
correctly.

Example: Add Location as an Applies-to Type


This example shows how to add a new location source type to the price list header.
The Price Source Type enum implements the Applies-to Type field in the header of the price list.
Additionally, the Sales Price Source Type , Purchase Price Source Type , and Job Price Source Type are
subsets of the Price Source Type enum. If we want to use a new value in sales, purchase, and job price lists, we
must also extend those enums.
In this example, we will extend the Price Source Type enum to display the value in the sales price lists by also
extending the Sales Price Source Type enum. For compatibility, the new value must have the same ID in both
enums.
enumextension 50001 "Location Source Type" extends "Price Source Type"
{
value(50001; Location)
{
Caption = 'Location';
Implementation = "Price Source" = "Price Source - Location", "Price Source Group" = "Price Source
Group - Customer";
}
}

enumextension 50003 "Location Sales Source Type" extends "Sales Price Source Type"
{
value(50001; Location)
{
Caption = 'Location';
}
}

The Price Source Type enum implements the Price Source and Price Source Group interfaces. We don't need
special source group handling here, and can reuse the existing implementation codeunit Price Source Group -
Customer . For the Price Source interface, we must add a new implementation codeunit Price Source -
Location . For examples, see the existing implementations of the Price Source interface.
The following example enables the new Applies-to Type on price lists.
codeunit 50003 "Price Source - Location" implements "Price Source"
{
var
Location: Record Location;
ParentErr: Label 'Parent Source No. must be blank for Location source type.';

procedure GetNo(var PriceSource: Record "Price Source")


begin
if Location.GetBySystemId(PriceSource."Source ID") then begin
PriceSource."Source No." := Location.Code;
FillAdditionalFields(PriceSource);
end else
PriceSource.InitSource();
end;

procedure GetId(var PriceSource: Record "Price Source")


begin
if Location.Get(PriceSource."Source No.") then begin
PriceSource."Source ID" := Location.SystemId;
FillAdditionalFields(PriceSource);
end else
PriceSource.InitSource();
end;

procedure IsForAmountType(AmountType: Enum "Price Amount Type"): Boolean


begin
exit(true);
end;

procedure IsSourceNoAllowed() Result: Boolean;


begin
Result := true;
end;

procedure IsLookupOK(var PriceSource: Record "Price Source"): Boolean


var
xPriceSource: Record "Price Source";
begin
xPriceSource := PriceSource;
if Location.Get(xPriceSource."Source No.") then;
if Page.RunModal(Page::"Location List", Location) = ACTION::LookupOK then begin
xPriceSource.Validate("Source No.", Location.Code);
PriceSource := xPriceSource;
exit(true);
end;
end;

procedure VerifyParent(var PriceSource: Record "Price Source") Result: Boolean


begin
if PriceSource."Parent Source No." <> '' then
Error(ParentErr);
end;

procedure GetGroupNo(PriceSource: Record "Price Source"): Code[20];


begin
exit(PriceSource."Source No.");
end;

local procedure FillAdditionalFields(var PriceSource: Record "Price Source")


begin
PriceSource.Description := Location.Name;
end;
}

Now lets ensure that price calculations include the new applies-to type.
To recalculate the price, we can subscribe to events that pass the sales line by reference. For example, the
OnValidateLocationCodeOnAfterSetOutboundWhseHandlingTime event. We'll call the
UpdateUnitPriceByLocationCode() method, which is a simplified version of the
UpdateUnitPriceByField() method that runs the price calculation on the Sales Line table.
To add the location in the source list for price calculations, we'll subscribe to the OnAfterAddSources event
of Codeunit "Sales Line - Price," and add the Location Code as a source of type Location .
The following example shows how.

codeunit 50004 "Location Source Price Calc."


{
[EventSubscriber(ObjectType::Table, Database::"Sales Line",
'OnValidateLocationCodeOnAfterSetOutboundWhseHandlingTime', '', false, false)]
local procedure OnValidateLocationCodeOnAfterSetOutboundWhseHandlingTime(var SalesLine: Record "Sales
Line");
begin
UpdateUnitPriceByLocationCode(SalesLine);
end;

local procedure UpdateUnitPriceByLocationCode(var SalesLine: Record "Sales Line")


var
SalesHeader: Record "Sales Header";
PriceCalculation: Interface "Price Calculation";
begin
SalesHeader.Get(SalesLine."Document Type", SalesLine."Document No.");
SalesLine.TestField("Qty. per Unit of Measure");

SalesLine.GetPriceCalculationHandler("Price Type"::Sale, SalesHeader, PriceCalculation);


if not (SalesLine."Copied From Posted Doc." and SalesLine.IsCreditDocType()) then begin
PriceCalculation.ApplyDiscount();
SalesLine.ApplyPrice(SalesLine.FieldNo("Location Code"), PriceCalculation);
end;
SalesLine.Validate("Unit Price");
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Sales Line - Price", 'OnAfterAddSources', '', false,


false)]
local procedure OnAfterAddSources(
SalesHeader: Record "Sales Header"; SalesLine: Record "Sales Line";
PriceType: Enum "Price Type"; var PriceSourceList: Codeunit "Price Source List");
begin
PriceSourceList.Add("Price Source Type"::Location, SalesLine."Location Code");
end;
}

Now we can test the price calculation. In this example, we have an East location where we keep item 1896-S,
and the item has prices for all customers.

We'll create a sales order and add four lines for our item. When we choose a location code, the value in the Unit
Price Excl. VAT changes.
Example: Add Hierarchical Price Calculations
This example adds a new price calculation method that changes the existing implementation to prioritize a
customer price over all other customer price, even if the price is higher. This requires a small adjustment to how
the price source list is generated, because the source list includes levels to implement hierarchical calculations.
The Price Calculation Method implements the price calculation methods. The following examples show how
to extend the enum with the new value.

enumextension 50005 "Hierarchical Price Method" extends "Price Calculation Method"


{
value(50005; Hierarchical)
{
Caption = 'Hierarchical';
}
}

We'll add a new codeunit that does the following:


Adds setup for the new method. Codeunit Price Calculation Mgt. provides the OnFindSuppor tedSetup
event that allows us to add Price Calculation Setup records. Subscribe to it, and add the default setup
record for the new method, for the sale type, all product types, and Business Central (Version 16.0)
implementation.
Modify the price source list that is generated by the Business Central (Version 16.0) implementation.
Codeunit Sales Line - Price provides the OnAfterAddSources event and passes the price source list that
can be overridden. Replace the incoming list with a new list that includes price sources at different levels,
where a higher level means a higher priority.
The following example shows how.
codeunit 50005 "Hierarchical Price Calc."
{

local procedure SetHierarchicalSourceList(SalesHeader: Record "Sales Header"; SalesLine: Record "Sales


Line"; var PriceSourceList: Codeunit "Price Source List")
begin
PriceSourceList.Init();
PriceSourceList.Add("Price Source Type"::"All Customers"); // "All Customers" will have lowest
priority
PriceSourceList.IncLevel();
PriceSourceList.Add("Price Source Type"::"Customer Price Group", SalesLine."Customer Price Group");
PriceSourceList.Add("Price Source Type"::"Customer Disc. Group", SalesLine."Customer Disc. Group");
PriceSourceList.IncLevel();
PriceSourceList.Add("Price Source Type"::Customer, SalesHeader."Bill-to Customer No."); // Customer
will have highest priority
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Price Calculation Mgt.", 'OnFindSupportedSetup', '',


false, false)]
local procedure OnFindSupportedSetup(var TempPriceCalculationSetup: Record "Price Calculation Setup");
begin
TempPriceCalculationSetup.Init();
TempPriceCalculationSetup.Method := TempPriceCalculationSetup.Method::Hierarchical;
TempPriceCalculationSetup.Enabled := true;
TempPriceCalculationSetup.Type := TempPriceCalculationSetup.Type::Sale;
TempPriceCalculationSetup."Asset Type" := TempPriceCalculationSetup."Asset Type"::" ";
TempPriceCalculationSetup.Validate(Implementation,
TempPriceCalculationSetup.Implementation::"Business Central (Version 16.0)");
TempPriceCalculationSetup.Default := true;
TempPriceCalculationSetup.Insert(true);
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Sales Line - Price", 'OnAfterAddSources', '', false,


false)]
local procedure OnAfterAddSources(SalesHeader: Record "Sales Header"; SalesLine: Record "Sales Line";
PriceType: Enum "Price Type"; var PriceSourceList: Codeunit "Price Source List");
begin
if SalesLine."Price Calculation Method" = "Price Calculation Method"::Hierarchical then
SetHierarchicalSourceList(SalesHeader, SalesLine, PriceSourceList);
end;
}

Now we can set up a price calculation method and see how it works in a sales order. Let's create a new price
calculation method named Hierarchical with one implementation for the sales type, as shown in the following
images.
On the Customer Card page for customer 10000, in the Price Calculation Method field we'll choose
Hierarchical , and in the Customer Price Group field we'll choose PRICEGROUP .

In the price list, we'll create price lines for item 1900-S so that the lowest price is for All Customers and the
highest is for customer 10000, as shown in the following image.

Now we'll create a sales order for customer 10000, and add a line for item 1900-S. The highest price is
suggested for the line because it is specified for the customer. If we clear the Price Calculation Method field
on the customer card, the lowest price will be suggested for the line if we create another order.
See Also
Extending Application Areas
Extending Pages Previously Based on the Date
Virtual Table
2/6/2023 • 2 minutes to read • Edit Online

INTRODUCED IN: Business Central 2020 release wave 1

Pages that previously had the Date virtual table as their source table have been redesigned so that they are
based on buffer tables instead. This way, base application pages such as Item Availability Lines and Res.
Availability Lines can now be extended.
To perform extensions on such pages, you must first extend the underlying buffer table. Then you create a
method that calculates and updates the values of the extended fields and subscribe it to the OnAfterCalcLine
event of the page.

Example
The following example illustrates how to add two new fields, "Add. -Currency Debit Amount" and
"Add. -Currency Credit Amount" , to the G/L Account Balance Lines page, which used to be based on the Date
table.
The first step is to create a Table Extension object and add the two fields, "Add.-Currency Debit Amount" and
"Add.-Currency Credit Amount" , to the G/L Account Balance Buffer source table. Then you create a Page
Extension object to display the fields in the G/L Account Balance Lines page. This is shown in the following
code.
tableextension 50001 GLAccBalanceBufferExt extends "G/L Acc. Balance Buffer"
{
fields
{
field(50001; "Add.-Currency Debit Amount"; Decimal)
{

}
field(50002; "Add.-Currency Credit Amount"; Decimal)
{

}
}
}

pageextension 50001 GLAccountBalanceLinesExt extends "G/L Account Balance Lines"


{
layout
{
addlast(Control1)
{

field(AddCurrencyDebitAmount; "Add.-Currency Debit Amount")


{

ApplicationArea = Basic, Suite;


Caption = 'Debit Amount (ACY)';
}

field(AddCurrencyCreditAmount; "Add.-Currency Credit Amount")


{
ApplicationArea = Basic, Suite;
Caption = 'Credit Amount (ACY)';
}
}
}
}

The subscriber method computes the values of the


GLAccountBalanceLinesOnAfterCalcLine
"Add.-Currency Credit Amount" and "Add.-Currency Debit Amount" fields and updates the G/L Acc. Balance
Buffer table. This method is called when the OnAfterCalcLine event in the G/L Account Balance Lines page
is raised.

codeunit 50001 GLAccountBalanceLinesExt


{
// Subscribe to OnAfterCalcLine event
[EventSubscriber(ObjectType::Page, Page::"G/L Account Balance Lines", 'OnAfterCalcLine', '', false,
false)]
local procedure GLAccountBalanceLinesOnAfterCalcLine(var GLAccount: Record "G/L Account"; var
GLAccBalanceBuffer: Record "G/L Acc. Balance Buffer")
begin

// Calculate values
GLAccount.CalcFields("Add.-Currency Credit Amount", "Add.-Currency Debit Amount");

// Assign calculated values to the new fields of the buffer table


GLAccBalanceBuffer."Add.-Currency Debit Amount" := GLAccount."Add.-Currency Debit Amount";
GLAccBalanceBuffer."Add.-Currency Credit Amount" := GLAccount."Add.-Currency Credit Amount";

end;
}
See Also
Page Extension object
Page object
CalcFields Method
Extending the Data Archive Extension
2/6/2023 • 2 minutes to read • Edit Online

The Data Archive extension provides a basic framework for archiving and backing up data as part of date
compression. When you use date compression you specify a date range and all entries within the range are
consolidated into a single entry, and the originals are deleted. For more information, see Compress Data with
Date Compression. However, there might be value in keeping that data, so rather than deleting it, you can use
the Data Archive extension to archive it for later use.
This article provides an example of how you can use the objects in the Data Archive extension so that your
application can also archive data. You'll use the Data Archive codeunit, which is available in the System
Application.
The following patterns of use are supported:
Store individual records by calling the SaveRecord(Record) method.
Store a record set by calling the SaveRecords(RecordRef ) method.
Start recording deletions by calling the StartSubscriptionToDelete() method in the beginning of your code,
and StopSubscriptionToDelete() after records have been deleted. Note that this pattern records all deletions,
including those that happen in related tables and intermediate tables that might be used in the process
(though temporary records are not recorded).

NOTE
Recording deletions relies on the global database triggers, so for any deletions that have already been made on the
relevant records, and if the change log is not active for that table, you should consider using
StartSubscriptionToDelete(true ) to reset the session. Resetting the session will, however, also reset the state in the object,
so we recommend caution when you test or use it.

The following example illustrates these patterns.


codeunit 50000 demo
{
trigger OnRun()
var
DataArchive: Codeunit "Data Archive";
begin
if DataArchive.DataArchiveProviderExists() then begin
SaveSingleRecords();
SaveRecordSet();
DeleteAndArchiveSomeCustomers();
end;
end;

local procedure SaveSingleRecords()


var
Customer: Record Customer;
DataArchive: Codeunit "Data Archive";
begin
Customer.SetRange("Country/Region Code", 'FO');
if Customer.FindSet() then begin
DataArchive.Create('Our Faroese customers');
repeat
DataArchive.SaveRecord(Customer);
until Customer.Next() = 0;
DataArchive.Save();
end;
end;

local procedure SaveRecordSet()


var
Customer: Record Customer;
DataArchive: Codeunit "Data Archive";
RecRef: RecordRef;
begin
Customer.SetRange("Country/Region Code", 'FO');
if not Customer.IsEmpty() then begin
DataArchive.Create('Our Faroese customers');
RecRef.GetTable(Customer);
DataArchive.SaveRecords(RecRef);
DataArchive.Save();
end;
end;

local procedure DeleteAndArchiveSomeCustomers()


var
Customer: Record Customer;
DataArchive: Codeunit "Data Archive";
begin
Customer.SetRange("Country/Region Code", 'FO');
if not Customer.IsEmpty() then begin
DataArchive.Create('Deleted Faroese customers');
DataArchive.StartSubscriptionToDelete();
Customer.DeleteAll(true);
DataArchive.StopSubscriptionToDelete();
DataArchive.Save();
end;
end;
}

Methods in the Data Archive codeunit


The following table lists the methods that the Data Archive codeunit provides.
M ET H O DS DESC RIP T IO N

procedure Create(Description: Text): Integer Creates a new archive entry.

procedure CreateAndStartLoggingDeletions(Description: Creates a new archive entry, resets the session and starts
Text): Integer logging all new del

procedure Open(ID: Integer) Opens an existing archive entry so more can be added to it

procedure Save() Saves and closes the currently open archive entry.

procedure DiscardChanges() Discards any additions and closes the currently open archive
entry.

procedure SaveRecord(RecordVar: Variant) Saves the supplied record to the currently open archive
procedure SaveRecord(var RecRef: RecordRef) entry.

procedure SaveRecords(var RecRef: RecordRef) Saves all records within the filters to the currently open
archive entry.

procedure StartSubscriptionToDelete() Starts subscription to the OnDatabaseDelete trigger and


procedure StartSubscriptionToDelete(ResetSession: Boolean) calls SaveRecord with any deleted record.

procedure StopSubscriptionToDelete() Stops the subscription to the OnDatabaseDelete trigger.

procedure DataArchiveProviderExists(): Boolean Informs the consumer app whether there is a provider for
this interface.

See Also
The Data Archive Extension
The Microsoft_Application.app File
Extending Application Areas
Extending Document Sharing and OneDrive for
Business Integration
2/6/2023 • 6 minutes to read • Edit Online

INTRODUCED IN: Business Central 2021 release wave 2

Business Central developers can tap into Microsoft 365 native file viewers and file sharing capabilities. This
article explains the document sharing capability. You'll learn how it's used with OneDrive for Business, and how
you can extend it.

Overview
Standard functionality in Business Central makes it easy for users to store, manage, and share files with other
people through OneDrive for Business. On most pages where files are available for downloading, users will find
an Open in OneDrive and Share action. They'll see this action, for example, on reports in the Repor t Inbox
or on files attached to records. For more information about the user experience, see Business Central and
OneDrive for Business Integration.
In the application code, the document sharing and OneDrive capabilities are divided between the system
application and the base application. The system application provides that platform working with document
sharing services—the base application makes it specific to OneDrive. As an AL developer, you can use the
system and base applications to extend the OneDrive capabilities. Or even target another document sharing
service.

NOTE
The Share action was introduced in Business Central 2022 release wave 1.

System application
The document sharing functionality is provided by the Document Sharing module. This module enables
document sharing flows through a valid document service, like OneDrive.

The Document Sharing module consists of two public objects:

TYPE ID NAME DESC RIP T IO N

Table 9560 Document Sharing A temporary table that


stores state information
about the document to be
shared, like the data BLOB,
file name and type.
TYPE ID NAME DESC RIP T IO N

Codeunit 9560 Document Sharing Performs the document


sharing. It uses the table
9560 Document Sharing
as its source, and must be
ran with a valid temporary
record from the table.

The codeunit includes the following trigger and methods:


OnRun() trigger and Share(var DocumentSharingRec: Record "Document Sharing") procedure
These two methods both trigger the documentation sharing flow. The difference is that OnRun() trigger
must be invoked with a document sharing record, like DocumentSharing.Run(TempDocumentSharing); . The
Share(var DocumentSharingRec: Record "Document Sharing") triggers the flow with a Document Sharing
record provided.
ShareEnabled(): Boolean

The method returns true if Document Sharing is enabled. Use this method as a quick test to, for example,
control visibility of a share action.
The OnRun() trigger and Share(var DocumentSharingRec: Record "Document Sharing") method raise two events
when run:
OnCanUploadDocument(var CanUpload: Boolean) for testing whether there are any document services that
can handle the upload.
OnUploadDocument(var DocumentSharing: Record "Document Sharing" temporary; var Handled: Boolean) for
uploading when the document to the service.
For more information about the API, see Document Sharing Module in the microsoft/ ALAppExtensions repo on
GitHub.

Base application
To support integration with OneDrive for Business, the base application uses the document sharing module of
the system application. Keep in mind that OneDrive itself is built on top of the SharePoint file platform.
Integration with OneDrive is made available through the SharePoint service on Microsoft Azure.

NOTE
With Business Central online the connection to the SharePoint service is done automatically. With on-premises, you have
to set it up manually. For more information, see Configuring Business Central On-premises for OneDrive Integration.

The core to the base application functionality for OneDrive integration is codeunit 9510 Document Ser vice
Management . This codeunit provides functions for storing documents to OneDrive through the SharePoint
service. Some points of interest are described below.
The base application is used to specify the URL of the document to be opened in OneDrive. The document
information is stored as record in the Document Sharing table. Documents can be stored and passed to
OneDrive as either BLOB or Media data types.
Codeunit 9510 Document Ser vice Management includes four procedures that run the Document Sharing
codeunit of the system application to start the document flow for either opening the document in OneDrive or
sharing the document with other in OneDrive:

M ET H O D DESC RIP T IO N

OpenInOneDrive(FileName: Text; FileExtension: Text; For copying documents stored as BLOBs to OneDrive and
InStream: InStream) opening the documents.

OpenInOneDriveFromMedia(FileName: Text; Fr sharing documents stored as Media to OneDrive and


FileExtension: Text; MediaId: Guid) opening the document.

ShareWithOneDrive(FileName: Text; FileExtension: For copying documents stored as BLOBs to OneDrive and
Text; InStream: InStream) sharing the documents with other people.

ShareWithOneDriveFromMedia(FileName: Text; For copying documents stored as BLOBs to OneDrive and


FileExtension: Text; MediaId: Guid) sharing the documents with other people.

These procedures call SetFileNameAndExtension(TempDocumentSharing, FileName, FileExtension) to set the file


name and extension of the document.
The codeunit includes two event subscribers that contain the logic for passing the document to OneDrive:
[EventSubscriber(ObjectType::Codeunit, Database::"Document Sharing", 'OnCanUploadDocument', '', false,
false)]
is called when the OnCanUploadDocument() event is raised by the Document Sharing codeunit. This
subscriber is used to verify whether the document can be uploaded, otherwise the flow is stopped.
[EventSubscriber(ObjectType::Codeunit, Database::"Document Sharing", 'OnUploadDocument', '', false,
false)]
is called when the OnUploadDocument() event is raised by the Document Sharing codeunit. This
subscriber retrieves the document information and passes it to target URL.
In an extension or embed app, subscribe to these events to target different document services. If you have
multiple services, provide users with a dialog that lets them choose the target.

System and Base application interaction


The following diagram illustrates the interaction between the system and base application. The diagram has
been simplified to show main points of interest. Although it shows the flow for opening in OneDrive, the flow is
similar for sharing.
Example
The following example extends the Posted Sales Invoice page of the base application to include an actions to
open and share a PDF version of a sales invoice in OneDrive.

NOTE
With Business Central 2022 release wave 2, the way that you promote actions on pages or page extensions has changed.
Promoting actions is defined in a specific section of the page definition and contains a reference to the action. For more
information, see Promoted Actions.

pageextension 50100 PostedSalesInvExt extends "Posted Sales Invoice"


{
actions
{
addafter(Email)
{
action(OpenInOneDrive)
{
// The properties provide a look and feel that's consistent with the OneDrive experience in
other places of the base application.
ApplicationArea = Basic, Suite;
Caption = 'Open in OneDrive';
ToolTip = 'Copy the file to your Business Central folder in OneDrive and open it in a new
window so you can manage or share the file.', Comment = 'OneDrive should not be translated';
Image = Cloud;
Promoted = true;
PromotedCategory = Category6;
PromotedOnly = true;

// Enables the action if connection is enabled.


Enabled = ShareOptionsEnabled;

trigger OnAction()
var
TempBlob: Codeunit "Temp Blob";
DocumentServiceManagement: Codeunit "Document Service Management";
InStr: InStream;
begin
GetInvoice(TempBlob);

TempBlob.CreateInStream(InStr);

// Helper to invoke document sharing flow


DocumentServiceManagement.OpenInOneDrive(StrSubstNo(SalesInvoiceName, Rec."No."),
'.pdf', InStr);
end;
}
}

action(ShareInOneDrive)
{
// The properties provide a look and feel that's consistent with the OneDrive experience in
other places of the base application.
ApplicationArea = Basic, Suite;
Caption = 'Share';
ToolTip = 'Copy the file to your Business Central folder in OneDrive and share it with other
people.', Comment = 'OneDrive should not be translated';
Image = Share;
Promoted = true;
PromotedCategory = Category6;
PromotedOnly = true;

// Enables the action if connection is enabled.


Enabled = ShareOptionsEnabled;

trigger OnAction()
var
TempBlob: Codeunit "Temp Blob";
DocumentServiceManagement: Codeunit "Document Service Management";
InStr: InStream;
begin
GetInvoice(TempBlob);

TempBlob.CreateInStream(InStr);

// Helper to invoke document sharing flow


DocumentServiceManagement.ShareWithOneDrive(StrSubstNo(SalesInvoiceName, Rec."No."),
'.pdf', InStr);
end;
}
}
}

var
ShareOptionsEnabled: Boolean;
SalesInvoiceName: Label 'Sales Invoice %1';

trigger OnOpenPage();
var
DocumentSharing: Codeunit "Document Sharing";
begin
ShareOptionsEnabled := DocumentSharing.ShareEnabled();
end;

local procedure GetInvoice(var TempBlob: Codeunit "Temp Blob")


var
ReportSelections: Record "Report Selections";
RecRef: RecordRef;
begin
RecRef.GetTable(Rec);
RecRef.SetRecFilter();

ReportSelections.GetPdfReportForCust(TempBlob, ReportSelections.Usage::"S.Invoice", RecRef,


Rec."Sell-to Customer No.");
end;
}

FAQ
Do I have to use the base application?
No. You can just use the system application. In this case, you'll have to create a codeunit, similar 9510
Document Ser vice Management , that handles the storage of documents and passing them to the online
service. The codeunit should subscribe to the events raised by codeunit 9560 Document Sharing .
Can I move files to OneDrive in the background?
No, this feature is designed for user interaction.
Can I specify filename and folder?
Yes, when you set record on the Document Sharing temporary table. But we'll provide better support for this
scenario in a later release.

See Also
Business Central and OneDrive for Business Integration
Overview of the System Application
Extending Application Areas
Extending Customer, Vendor, and Item Templates
2/6/2023 • 3 minutes to read • Edit Online

You can extend customer, vendor, and item templates, or create your own template and use it for primary tables.
The following sections provide examples.

Example: Extend an existing customer template by adding a field


You can add a field to a customer template, and then include the field when someone uses the template to create
a new customer. You just need to add field with the same number, type, and length, to the Customer and
Customer Templ. tables. Dynamics 365 Business Central will transfer value from the template to new records.

Example: Use configuration templates


This example shows how use configuration templates instead of creating new templates.

codeunit 50102 ConfigTemplateExtMgt


{
trigger OnRun()
begin
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Customer Templ. Mgt.",


'OnBeforeCreateCustomerFromTemplate', '', false, false)]
local procedure OnBeforeCreateCustomerFromTemplateHandler(var Customer: Record Customer; var Result:
Boolean; var IsHandled: Boolean)
var
MiniCustomerTemplate: Record "Mini Customer Template";
begin
IsHandled := true;
Result := MiniCustomerTemplate.NewCustomerFromTemplate(Customer);
end;
}

Example: Verify the fields you added to extend existing primary


template table and template card
This example shows how to verify the fields you added to existing templates with a data and template card. You
can run this procedure in tests, for example, to ensure that the fields you added on the Customer Card page also
exist on the Customer Template Card page.
procedure CustomerTemplCardControls()
var
CustomerCardPageControlField: Record "Page Control Field";
CustomerTemplCardPageControlField: Record "Page Control Field";
CustomerTemplField: Record Field;
begin
CustomerTemplCardPageControlField.SetRange(PageNo, Page::"Customer Templ. Card");

CustomerCardPageControlField.SetRange(PageNo, Page::"Customer Card");


CustomerCardPageControlField.SetFilter(FieldNo, '<>0');
if CustomerCardPageControlField.FindSet() then
repeat
if CustomerTemplField.Get(Database::"Customer Templ.", CustomerCardPageControlField.FieldNo)
then begin
CustomerTemplCardPageControlField.SetRange(FieldNo,
CustomerCardPageControlField.FieldNo);
if CustomerTemplCardPageControlField.IsEmpty then
Error('%1 should exist on the customer template card.',
CustomerCardPageControlField.ControlName);
end;
until CustomerCardPageControlField.Next() = 0;
end;

Example: Create a new template for the primary table


This example shows how to create a template for the Resource table, and then use the template to create a new
resource. Let's extend the Resource table by adding a new field named Extension Field .

tableextension 50101 ResourceExt extends Resource


{
fields
{
field(50101; "Extension Field"; Text[50])
{
Caption = 'Extension Field';
}
}
}

pageextension 50102 ResourceCardExt extends "Resource Card"


{
layout
{
addlast(General)
{
field("Extension Field"; "Extension Field")
{
ApplicationArea = All;
}
}
}
}

Here's a new template table for resources.


table 50103 "Resource Template"
{
fields
{
field(1; Code; Code[20])
{
Caption = 'Code';
NotBlank = true;
}
field(14; "Resource Group No."; Code[20])
{
Caption = 'Resource Group No.';
TableRelation = "Resource Group";
}
field(50100; "Template Description"; Text[50])
{
Caption = 'Template Description';
}
field(50101; "Extension Field"; Text[50])
{
Caption = 'Extension Field';
}
}

keys
{
key(Key1; Code)
{
Clustered = true;
}
}
}

The following card and list pages for the new template allow you to edit the template, or select it when you
create a new resource.
page 50104 "Resource Template Card"
{
PageType = Card;
SourceTable = "Resource Template";

layout
{
area(Content)
{
group(General)
{
Caption = 'General';

field(Code; Code)
{
ApplicationArea = All;
}
field("Template Description"; "Template Description")
{
ApplicationArea = All;
}
}
group(Details)
{
Caption = 'Details';

field("Resource Group No."; "Resource Group No.")


{
ApplicationArea = All;
}
field("Extension Field"; "Extension Field")
{
ApplicationArea = All;
}
}
}
}
}

page 50105 "Resource Template List"


{
Caption = 'Resource Templates';
PageType = List;
ApplicationArea = All;
UsageCategory = Lists;
SourceTable = "Resource Template";
CardPageId = "Resource Template Card";

layout
{
area(Content)
{
repeater(Templates)
{
field(Code; Code)
{
ApplicationArea = All;
}
field("Template Description"; "Template Description")
{
ApplicationArea = All;
}
}
}
}
}
The following management codeunit runs the template list page for selecting templates when you create a new
resource. It also transfers data from the Extension Field and Resource Group No. fields from the template to
the Resource record.

codeunit 50101 TemplateExtMgt


{
SingleInstance = true;

trigger OnRun()
begin
end;

var
ResourceNewMode: Boolean;

local procedure CreateResourceFromTemplate(var Resource: Record Resource)


var
SrcResource: Record Resource;
ResourceTemplate: Record "Resource Template";
begin
if not ResourceNewMode then
exit;

ResourceNewMode := false;

if not SelectResourceTemplate(ResourceTemplate) then


exit;

SrcResource.Init();
SrcResource.Insert(true);

SrcResource."Resource Group No." := ResourceTemplate."Resource Group No.";


SrcResource."Extension Field" := ResourceTemplate."Extension Field";
SrcResource.Modify();

Resource.Copy(SrcResource);
end;

local procedure SelectResourceTemplate(var ResourceTemplate: Record "Resource Template"): Boolean


var
ResourceTemplateList: Page "Resource Template List";
begin
if ResourceTemplate.Count = 1 then begin
ResourceTemplate.FindFirst();
exit(true);
end;

if (ResourceTemplate.Count > 1) and GuiAllowed then begin


ResourceTemplateList.SetTableView(ResourceTemplate);
ResourceTemplateList.LookupMode(true);
if ResourceTemplateList.RunModal() = Action::LookupOK then begin
ResourceTemplateList.GetRecord(ResourceTemplate);
exit(true);
end;
end;

exit(false);
end;

[EventSubscriber(ObjectType::Page, Page::"Resource Card", 'OnNewRecordEvent', '', false, false)]


local procedure OnNewRecordEventHandler()
begin
ResourceNewMode := true;
end;

[EventSubscriber(ObjectType::Page, Page::"Resource Card", 'OnAfterGetCurrRecordEvent', '', false,


false)]
local procedure OnAfterGetCurrRecordEventHandler(var Rec: Record Resource)
local procedure OnAfterGetCurrRecordEventHandler(var Rec: Record Resource)
begin
CreateResourceFromTemplate(Rec);
end;

[EventSubscriber(ObjectType::Page, Page::"Resource Card", 'OnBeforeOnAfterGetCurrRecord', '', false,


false)]
local procedure OnBeforeOnAfterGetCurrRecordHandler(sender: Page "Resource Card")
begin
sender.Update();
end;
}

See Also
Extending Application Areas
Extend Email Capabilities
2/6/2023 • 7 minutes to read • Edit Online

Business Central offers built-in email capabilities that cover the needs of most businesses. You can share
documents and information by email directly from Business Central.
However, you might have a bright idea for something extra that would benefit your, or your customers',
business. For example, you might want to use an email scenario that we don't provide. This article describes how
you can extend the key components of our standard email capabilities.

Email architecture overview


The following diagram shows the key components of the out-of-the-box email capabilities.

C O M P O N EN T DESC RIP T IO N

Email scenarios Define the business processes for which an email account will
be used by default.

Email address book lookup Sets how you find email addresses for specific entities.

Email view policies Determine who has access to which email messages.

Email accounts and connectors Specify the email providers and accounts that are connected
to Business Central.

Email Outbox and Sent Email pages Contain messages that haven't been sent, or have been sent,
respectively.

We'll explore each of these components in more depth, and provide an example of how to extend their
capabilities.

Email scenarios
Email scenarios are processes that involve sending a document. For example, a sales or purchase order or a
notification that gives an external accountant access to your Business Central. You can use specific email
accounts for specific scenarios. The following are a few examples:
All users always send sales documents from account A.
All users always send purchase documents from account B.
All users always send warehouse or production documents from account C.
The following diagram shows the relationship between the objects for email scenarios.

The following code example shows how to extend the Email Scenario enum by adding a new scenario named
BC LE Scenario . After you extend the enum, the new BC LE option is available in the Email Scenario field. You
can assign the scenario to accounts on the Email Scenarios page, or by using the
EmailScenario.SetEmailAccount() method.

enumextension 50100 BCLEScenario extends "Email Scenario"

{
value(999888; BCLEScenario)
{
Caption = 'BC LE Scenario';
}
}

procedure AddEmailToScenario(Rec: Record "Email Account")


var
EmailScenario: Codeunit "Email Scenario";
NullGuid: Guid;
begin
if Rec."Account Id" <> NullGuid then
EmailScenario.SetEmailAccount(Enum::"Email Scenario"::BCLEScenario, Rec)
else
Error('Trying to set an empty email account to BCLE email scenario');
end;
Email address book lookup
The email address book lookup is what you use to choose email accounts in Business Central from entities such
as customers and vendors. The following diagram shows the relationship between the objects for the email
address book lookup.

The following code example shows how to extend the Email Address Entity enum by adding a BCLE Entity
option. The BCLE entity has an email address that we want to be able to access.

enumextension 50110 "BCLE - Address Book" extends "Email Address Entity"

{
value(50110; "BCLE Entity")
{
Caption = 'BCLE Entity';
}
}

After you extend the Email Address Entity enum, subscribe to the OnGetSuggestedAddresses and
OnLookupAddressFromEntity events. These events do the following:
OnGetSuggestedAddresses gets email addresses from the records in the table that are related to an email that
you are composing and displays them in the address book.
OnLookupAddressFromEntity opens a modal dialog where you can choose the email addresses to add to the
address book.
The following examples show how to implement the events.

[IntegrationEvent(false, false)]
internal procedure OnGetSuggestedAddresses(TableId: Integer; SystemId: Guid; var Address: Record "Email
Address Lookup")

[IntegrationEvent(false, false)]
internal procedure OnLookupAddressFromEntity(Entity: Enum "Email Address Entity"; var Address: Record "Email
Address Lookup"; var IsHandled: Boolean)

var
NoRecordsFoundMsg: Label 'No %1 found with an email address.', Comment = '%1 Entity type';
NoRecordsFoundMsg: Label 'No %1 found with an email address.', Comment = '%1 Entity type';

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Email Address Lookup", 'OnLookupAddressFromEntity', '',


false, false)]
local procedure OnLookupAddressFromEntity(Entity: Enum "Email Address Entity"; var Address: Record "Email
Address Lookup"; var IsHandled: Boolean)
var
BCLEEntity: Record "BCLE Entity";
BCLEEntityList: Page "BCLE Entity List";
begin
if not BCLEEntity.ReadPermission() or IsHandled or (Entity <> Entity::"BCLE Entity") then
exit;

BCLEEntity.SetFilter("Email", '<>%1', '');


if not BCLEEntity.FindSet() then begin
Message(StrSubstNo(NoRecordsFoundMsg, BCLEEntity.TableCaption));
exit;
end;

BCLEEntityList.SetTableView(BCLEEntity);
BCLEEntityList.LookupMode := true;

if BCLEEntityList.RunModal() <> ACTION::LookupOK then begin


IsHandled := false;
exit;
end;

BCLEEntityList.SetSelectionFilter(BCLEEntity);
if BCLEEntity.FindSet() then
repeat
if StrLen(BCLEEntity.Email) > 0 then begin
Address.Name := BCLEEntity."Speaker Name";
Address."E-Mail Address" := BCLEEntity.Email;
Address."Source Table Number" := Database::"BCLE Entity";
Address."Source System Id" := BCLEEntity.SystemId;
Address."Entity type" := Enum::"Email Address Entity"::"BCLE Entity";
Address.Insert();
IsHandled := true;
end;
until BCLEEntity.Next() = 0;
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Email Address Lookup", 'OnGetSuggestedAddresses', '',


false, false)]
local procedure SuggestedAddressesFromContacts(TableId: Integer; SystemId: Guid; var Address: Record "Email
Address Lookup")
var
BCLEEntity: Record "BCLE Entity";
CompanyNo: Code[20];
begin
case TableId of
Database::"BCLE Entity":
begin
if not BCLEEntity.GetBySystemId(SystemId) then
exit;
InsertAddressFromBCLEEntity(BCLEEntity, Address);
end;
else
exit;
end;
end;

local procedure InsertAddressFromBCLEEntity(var BCLEEntity: Record "BCLE Entity"; var Address: Record "Email
Address Lookup")
begin
if ((BCLEEntity.Email <> '') and not Address.Get(BCLEEntity.Email, BCLEEntity."Speaker Name",
Enum::"Email Address Entity"::"BCLE Entity")) then begin
Address.Name := BCLEEntity."Speaker Name";
Address."E-Mail Address" := BCLEEntity.Email;
Address."Source Table Number" := Database::"BCLE Entity";
Address."Source Table Number" := Database::"BCLE Entity";
Address."Source System Id" := BCLEEntity.SystemId;
Address."Entity type" := Enum::"Email Address Entity"::"BCLE Entity";
Address.Insert();
end;
end;

Email view policies


Email view policies give you control over the email messages that a user can access on the Email Outbox and
Sent Emails pages. You can extend email view policies, for example by adding new policies, by customizing their
types. The following diagram shows the relationship between the objects for email view policies.

The first step is to implement the Email View Policy interface.

interface "Email View Policy"

{
procedure GetSentEmails(var SentEmails: Record "Sent Email" temporary);
procedure GetOutboxEmails(var OutboxEmails: Record "Email Outbox" temporary);
procedure GetSentEmails(SourceTableId: Integer; var SentEmails: Record "Sent Email" temporary);
procedure GetOutboxEmails(SourceTableId: Integer; var OutboxEmails: Record "Email Outbox" temporary);
procedure GetSentEmails(SourceTableId: Integer; SourceSystemId: Guid; var SentEmails: Record "Sent
Email" temporary);
procedure GetOutboxEmails(SourceTableId: Integer; SourceSystemId: Guid; var OutboxEmails: Record "Email
Outbox" temporary);
procedure HasAccess(SentEmail: Record "Sent Email"): Boolean;
procedure HasAccess(OutboxEmail: Record "Email Outbox"): Boolean;
}

Next, we'll extend the Email View Policy enum by adding a BE LE View Policy option.
enumextension 50108 "BC LE View Policy" extends "Email View Policy"

{
value(50108; "BC LE View Policy")
{
Caption = 'BC LE View Policy';
Implementation = "Email View Policy" = BCLEViewPolicy;
}
}

The last step is to assign the email view policies to users. For more information, see Set Up View Policies.

Email accounts and connectors


A connector is the interface for creating and managing email accounts, and for sending emails from the
accounts. The following table lists the connectors that are available by default.

C O N N EC TO R DESC RIP T IO N

Microsoft 365 Connector Everyone sends email from a shared mailbox in Exchange
Online.

Current User Connector Everyone sends email from the account they used to sign in
to Business Central.

SMTP Connector Use SMTP protocol to send emails.

NOTE
The Microsoft 365 Connector and Current User Connector require that the user has a mailbox on the tenant.

All email accounts use a connector, and the accounts contain the information needed to send email messages.
The following diagram shows the relationship between the objects for email accounts and connectors.
The first step is to implement the Email Connector interface.

interface "Email Connector"

{
procedure Send(EmailMessage: Codeunit "Email Message"; AccountId: Guid);
procedure GetAccounts(var Accounts: Record "Email Account");
procedure ShowAccountInformation(AccountId: Guid);
procedure RegisterAccount(var EmailAccount: Record "Email Account"): Boolean
procedure DeleteAccount(AccountId: Guid): Boolean
procedure GetLogoAsBase64(): Text;
procedure GetDescription(): Text[250];
}

Next, we'll extend the Email Connector enum by adding an SMTP option.

{
value(2147483647; SMTP)
{
Caption = 'SMTP';
Implementation = "Email Connector" = "SMTP Connector Impl.";
}
}

The last step is to create a page where we can view or create an email account. For more information, see Pages
Overview.

TIP
If you want more details, there are several examples available on the AlAppExtensions repository. For example, the SMTP
Connector is a good implementation to explore.
Email Importance Enum

enum 50109 "Email Importance"


{
Extensible = true;

value(0; Normal)
{
Caption = 'Normal';
}

value(1; Important)
{
Caption = 'Important';
}

value(2; "Super Important")


{
Caption = 'Super Important';
}
}

Table extensions to add a new Importance field.

tableextension 50110 "Importance On Sent" extends "Sent Email"


{
fields
{
field(50109; "Importance"; Enum "Email Importance")
{
DataClassification = SystemMetadata;
}
}
}

tableextension 50109 "Importance On Outbox" extends "Email Outbox"


{
fields
{
field(50109; "Importance"; Enum "Email Importance")
{
DataClassification = SystemMetadata;
}
}
}

Page extensions on the Email Editor and Email Viewer that allow the Importance field to be viewed and changed.

pageextension 50111 "Importance On Editor" extends "Email Editor"


{
layout
{
addafter(CcField)
{
field(Importance; Rec.Importance)
{
ApplicationArea = All;
Caption = 'Importance';
ToolTip = 'Specifies the importance of the email';
}
}
}
}
pageextension 50103 "Importance On Email Viewer" extends "Email Viewer"
{
layout
{
addafter(CcField)
{
field(Importance; Rec.Importance)
{
ApplicationArea = All;
Caption = 'Importance';
ToolTip = 'Specifies the importance of the email';
}
}
}
}

Page extensions for the Email Outbox and Sent Emails to display the Importance field.

pageextension 50109 "Importance On Outbox" extends "Email Outbox"


{
layout
{
addafter(Desc)
{
field(Importance; Rec.Importance)
{
ApplicationArea = All;
Caption = 'Importance';
ToolTip = 'Specifies the importance of the email';
}
}
}
}

pageextension 50110 "Importance On Sent" extends "Sent Emails"


{
layout
{
addafter(Desc)
{
field(Importance; Rec.Importance)
{
ApplicationArea = All;
Caption = 'Importance';
ToolTip = 'Specifies the importance of the email';
}
}
}
}

See Also
Overview of the System Application
Set Up Email
Extending G/L Entry Aggregations When Posting
Invoices
2/6/2023 • 3 minutes to read • Edit Online

IMPORTANT
This feature is currently available only for sandbox environments. Do not use it in production environments.

This article provides an example of how to customize the way that G/L entries are aggregated when you post
sales, purchase, and service documents.
Extend the posting process for sales, purchase, and service documents by changing the way the posting
algorithm aggregates G/L entries. For example, for specific document lines, posting groups, or the tax setup
required by local legislation. Replace customizations to G/L invoice posting by using the Invoice Posting
interface, resolve issues for the legacy Invoice Post. Buffer table, and use your own implementation of G/L
invoice posting.

NOTE
The Invoice Post. Buffer table has been an important part of localizations and customizations for businesses that must
aggregate lines on sales, purchase, and service document lines in a specific way when they post the documents in order
to comply with local, industry, or customer requirements. Historically, this design wasn't extensible because we couldn't
change the primary key in the Invoice Post. Buffer table without introducing a breaking change in third-party solutions
and localizations.
We've removed the dependencies from the Invoice Posting Buffer table in the Base Application and built an Invoice
Posting object with an interface and an extensible enum for the implementation setup. For more information, see The
Objects to Use

The Objects to Use for Your Extension


The Invoice Posting interface provides a set of procedures for posting sales, purchase, and service invoices.
This interface let's you replace the invoice posting implementation for an extension.

NOTE
The legacy implementation is still available in posting codeunits, but are tagged as obsolete .

The Sales Invoice Posting . Purchase Invoice Posting , and Ser vice Invoice Posting enums are
extensible and define the current implementation.
The following is an example of an implementation that uses the Sales Invoice Posting enum.
enum815"SalesInvoicePosting"implements"InvoicePosting"
{
Extensible=true;

value(0;"InvoicePosting(Default)")
{
Caption='InvoicePosting(Default)';
Implementation="InvoicePosting"="UndefinedPostInvoice";
}

value(815;"InvoicePosting(v.19)")
{
Caption='InvoicePosting(v.19)';
Implementation="InvoicePosting"="SalesPostInvoice";
}
}

The temporary Invoice Posting Buffer table uses the generic key, Group ID: Text[1000] . You can use the
BuildPrimaryKey() method to compose the key from table fields. The OnAfterBuildPrimaryKey event can be
used to compose the primary key in a different way.
The Invoice Posting Setup field on the purchase and service setup tables lets you define the
implementation for the (Sales) Invoice Posting codeunit. If you define the value Invoice Posting (v.19) , the
Base Application will run codeunit 815 Sales Invoice Posting from the Sales-Post codeunit for your
customized posting process.
Typically, you'll only need to add fields to the Invoice Posting Buffer table.

Example: Post G/L entries according to your product line code


1. Add a new Product Line Code field to the Invoice Posting Buffer table in your extension. The
following code sample shows how.

tableextension50000"InvoicePostingBufferExt."extends"InvoicePostingBuffer"
{
fields
{
field(50000;"ProductLineCode";Code[10])
{
Caption='ProductLineCode';
}
}
}

2. After you have a Product Line Code field on sales lines, add subscribers as shown in the following code
sample.
codeunit50000"ProductLineSubscribers"
{

[EventSubscriber(ObjectType::Codeunit,Codeunit::"SalesPostInvoice",'OnPrepareLineOnAfterFillInvoicePo
stingBuffer','',false,false)]
localprocedureOnPrepareLineOnAfterFillInvoicePostingBuffer(varInvoicePostingBuffer:Record"InvoicePost
ingBuffer";SalesLine:Record"SalesLine")
begin
InvoicePostingBuffer."ProductLineCode":=SalesLine."ProductLineCode";
end;

[EventSubscriber(ObjectType::Table,Database::"InvoicePostingBuffer",'OnAfterBuildPrimaryKey','',false
,false)]
localprocedureInvoicePostingBufferOnAfterBuildPrimaryKey(varInvoicePostingBuffer:Record"InvoicePostin
gBuffer")
begin
//ProductLineCodevalueaddedasfirstfieldtotheexistingprimarykeyasexample
//althoughHroupIDfieldcanbecomposedinanyalternativewaytosupportanothersortingand
//aggregationofG/Lentriesforposting
InvoicePostingBuffer."GroupID":=
InvoicePostingBuffer.PadField(InvoicePostingBuffer."ProductLineCode",MaxStrLen(InvoicePostingBuffer."
ProductLineCode"))+
InvoicePostingBuffer."GroupID";
end;
}

3. Use your extension to set the Invoice Posting (v.19) value in the Invoice Posting Setup field on the
Sales & Receivables Setup table. The Invoice Posting Setup field is not available on the Sales &
Receivables Setup page to prevent the Invoice Posting interface from being misconfigured.

Advanced Scenarios
In more advanced scenarios, you can create your own implementation codeunit and use it instead of codeunit
815 Sales Post Invoice, implement interface methods, and add your values to the Sales Invoice Posting enum.
You can then use any methods for aggregation of G/L entries.

See Also
The Microsoft_Application.app File
Publishing a Code-Customized Base Application for Business Central On-Prem
Extending Application Areas
Event Types
2/6/2023 • 8 minutes to read • Edit Online

Dynamics 365 Business Central supports different types of events for different purposes.

Business events
A business event is a custom event that is raised by AL code. It defines a formal contract that carries an implicit
promise not to change in future releases. It is the expectation that business events are published by solution
ISVs, including Microsoft.
Business events can be compared with publicly released APIs on which 3rd party solution providers develop
integrations and additions. Therefore, the downstream cost of making changes to a business event
implementation can be considerable for those who use the event in their applications. There may be some cases
where changes are required; however, you should keep these to an absolute minimum.
Development considerations
A typical business event reflects changes in “state” with regards to a process. This makes them very well suited
for workflow. An example of a business event could be when a sales order has been posted. It is important to
note that business events should not be tied to the implementation-details, such as the tables or fields in which
the data is stored. Preferably, the event publisher developer should be free to change the implementation, while
still keeping the business event intact. To learn about the syntax and example on how to use the BusinessEvent
type, see BusinessEvent Attribute.
Business events should be documented with the solution, including the before-state and after-state of the
events.

Integration events
An integration event is also a custom event that is raised by AL code, like a business event, except that it does
not carry the same promise of not changing, nor does it have the restriction not to expose implementation
details.
The main purpose of integration events is to enable the integration of other solutions with Dynamics 365
Business Central without having to perform traditional code modifications.
Development considerations
An integration event can be changed to a business event later. At which time, it must adhere to the same implied
contract and commitment as any business event. It can also simply be designed-in hook points for external add-
ons. To learn about the syntax and example on how to use the IntegrationEvent type, see IntegrationEvent
Attribute.
Development considerations
To learn about the syntax and example on how to use the InternalEvent type, see InternalEvent Attribute.

Global events
Global events are predefined system events that are automatically raised by various base application codeunits.
For example, codeunit 40 LoginManagement includes several global method triggers, such as CompanyOpen,
CompanyClose, and GetSystemIndicator. For most of these global method triggers, there are one or two global
events: a before and after event. For example, there is an OnBeforeCompanyOpen event and an
OnAfterCompanyOpen event. The global events are defined as integration event publishers by local methods in
the following codeunits.

C O DEUN IT ID C O DEUN IT N A M E EVEN T

9170 Conf./Personalization Mgt. OnRoleCenterOpen

OnAfterLogInEnd

OnBeforeLogInStart

OnBeforeCompanyOpen

OnAfterCompanyOpen

OnBeforeCompanyClose

OnAfterCompanyClose

42 TextManagement OnBeforeMakeTextFilter

OnAfterMakeDateTimeFilter

OnAfterMakeDateFilter

OnAfterMakeTextFilter

OnAfterMakeTimeFilter

42* Caption Class OnAfterCaptionClassResolve

OnResolveCaptionClass

44 ReportManagement OnAfterGetPrinterName

OnAfterDocumentPrintReady

OnAfterGetPaperTrayForReport

OnAfterGetPrinterName

OnAfterHasCustomLayout

OnAfterDocumentReady

OnAfterDocumentDownload

OnAfterSetupPrinters

OnCustomDocumentMergerex

OnAfterSubstituteReport
C O DEUN IT ID C O DEUN IT N A M E EVEN T

45 AutoFormatManagement OnAfterAutoFormatTranslate

49 GlobalTriggerManagement OnAfterGetGlobalTableTriggerMask

OnAfterOnGlobalInsert

OnAfterOnGlobalModify

OnAfterOnGlobalDelete

OnAfterOnGlobalRename

OnAfterGetDatabaseTableTriggerSetup

OnAfterOnDatabaseInsert

OnAfterOnDatabaseModify

OnAfterOnDatabaseDelete

OnAfterOnDatabaseRename

OnBeforeOnDatabaseInsert

OnBeforeOnDatabaseModify

OnBeforeOnDatabaseDelete

OnBeforeOnDatabaseRename

* Codunit 42 Caption Class was introduced as a replacement for codeunit 42 CaptionManagement . In


previous versions, codeunit 42 CaptionManagement included the OnAfterCaptionClassTranslate event. For
more information, see Breaking Changes in the ALAppExtensions GitHub repo.

Trigger events
Unlike business and integration events which must be programmed, trigger events are predefined events.
Trigger events are published by the runtime and they cannot be raised programmatically. There are two types of
trigger events: database trigger events and page trigger events.

NOTE
Trigger events do not appear as methods in AL for a table or page object.

Database trigger events


Trigger events are automatically raised by the system when it performs database operations on a table object,
such as deleting, inserting, modifying, and renaming a record, as defined in a table. Trigger events are closely
associated with the table triggers for database operations: OnDelete, OnInsert, OnModify, OnRename, and
OnValidate (for fields). For each database operation, there is a "before" and "after" trigger event with a fixed
signature.
Available Database Trigger Events
The following table describes the available database trigger events:

DATA B A SE T RIGGER EVEN T SIGN AT URE DESC RIP T IO N

OnAfterDeleteEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed after a record is deleted from


Database::<Table Name>, a table.
'OnAfterDeleteEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; RunTrigger:
Boolean)

OnAfterInsertEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed after a record is inserted in a


Database::<Table Name>, table.
'OnAfterInsertEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; RunTrigger:
Boolean)

OnAfterModifyEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed after a record is modified in a


Database::<Table Name>, table.
'OnAfterModifyEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
RunTrigger: Boolean)

OnAfterRenameEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed after a record is renamed in a


Database::<Table Name>, table.
'OnAfterRenameEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
RunTrigger: Boolean)

OnAfterValidateEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed after a field is validated when


Database::<Table Name>, its value has been changed.
'OnAfterValidateEvent', '<Field
Name>', <SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
CurrFieldNo: Integer)

OnBeforeDeleteEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed before a record is deleted


Database::<Table Name>, from a table.
'OnBeforeDeleteEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; RunTrigger: Boolean)

OnBeforeInsertEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed before a record is inserted in


Database::<Table Name>, a table.
'OnBeforeInsertEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; RunTrigger: Boolean)
DATA B A SE T RIGGER EVEN T SIGN AT URE DESC RIP T IO N

OnBeforeModifyEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed before a record is modified in


Database::<Table Name>, a table.
'OnBeforeModifyEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
RunTrigger: Boolean)

OnBeforeRenameEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed before a record is renamed in


Database::<Table Name>, a table.
'OnBeforeRenameEvent', '',
<SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
RunTrigger: Boolean)

OnBeforeValidateEvent Trigger Event [EventSubscriber(ObjectType::Table, Executed before a field is validated


Database::<Table Name>, when its value has been changed.
'OnBeforeValidateEvent', '<Field
Name>', <SkipOnMissingLicense>,
<SkipOnMissingPermission>)]
procedure MyProcedure(var Rec:
Record; var xRec: Record;
CurrFieldNo: Integer)

The following table describes the parameters of the trigger events:

PA RA M ET ER TYPE DESC RIP T IO N

Rec Record The table that raises the event.

xRec Record The table that raises the event.

RunTrigger Boolean Specifies whether to execute the code


in the event trigger when it is invoked.
If this parameter is true, the code will
be executed. If this parameter is false,
then the code is not executed.

CurrFieldNo Integer The number of the field that raises the


event.

Order of Event Execution


The relative order of execution of database trigger events, table triggers, and database operations is as follows:

O RDER IT EM EXA M P L E

1 Trigger event (before) OnBeforeDeleteEvent

2 Table trigger OnDelete

3 Global table trigger in codeunit OnDatabaseDelete

4 Database operations Delete the record

5 Trigger event (after) OnAfterDeleteEvent


Page trigger events
Page Trigger events are raised automatically by the system when it performs certain operations in a page object.
Page trigger events are closely associated with the standard page triggers, such as OnOpenPage, OnClosePage,
and OnAction.
Available Page Trigger Events
The following table describes the available page trigger events:

T RIGGER EVEN T SIGN AT URE DESC RIP T IO N

OnAfterActionEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnAction trigger,


Page::<Page Name>, which is called when a user selects an
'OnAfterActionEvent', '<Action
Name>', <SkipOnMissingLicense>, action on the page.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record)

OnAfterGetCurrRecordEvent Trigger [EventSubscriber(ObjectType::Page, Executed after the


Event Page::<Page Name>, OnAfterGetCurrRecord trigger, which is
'OnAfterGetCurrRecordEvent', '',
<SkipOnMissingLicense>, called after the current record is
<SkipOnMissingPermission>)] retrieved from the table.
local procedure MyProcedure(var
Rec: Record)

OnAfterGetRecordEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the


Page::<Page Name>, OnAfterGetCurrRecord trigger, which is
'OnAfterGetRecordEvent', '',
<SkipOnMissingLicense>, called after the record is retrieved from
<SkipOnMissingPermission>)] the table but before it is displayed to
local procedure MyProcedure(var the user.
Rec: Record)

OnAfterValidateEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnValidate (Page


Page::<Page Name>, fields) trigger, which is called when a
'OnAfterValidateEvent', '<Control
Name>', <SkipOnMissingLicense>, field loses focus after its value has
<SkipOnMissingPermission>)] been changed.
local procedure MyProcedure(var
Rec: Record; var xRec: Record)

OnBeforeActionEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed before the OnAction trigger,


Page::<Page Name>, which is called when a user selects an
'OnBeforeActionEvent', '<Action
Name>', <SkipOnMissingLicense>, action on the page.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record)

OnBeforeValidateEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed before the OnValidate (Page


Page::<Page Name>, fields) trigger, which is called when a
'OnBeforeValidateEvent', '<Control
Name>', <SkipOnMissingLicense>, field loses focus after its value has
<SkipOnMissingPermission>)] been changed.
local procedure MyProcedure(var
Rec: Record; var xRec: Record)

OnClosePageEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnClosePage


Page::<Page Name>, trigger, which is called when page
'OnClosePageEvent', '',
<SkipOnMissingLicense>, closes after the OnQueryClosePage
<SkipOnMissingPermission>)] trigger is executed.
local procedure MyProcedure(var
Rec: Record)
T RIGGER EVEN T SIGN AT URE DESC RIP T IO N

OnDeleteRecordEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnDeleteRecord


Page::<Page Name>, trigger, which is called before a record
'OnDeleteRecordEvent', '',
<SkipOnMissingLicense>, is deleted from a table.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; var AllowDelete:
Boolean)

OnInsertRecordEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnInsertRecord


Page::<Page Name>, trigger, which is called before a record
'OnInsertRecordEvent', '',
<SkipOnMissingLicense>, is inserted in a table.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; BelowxRec: Boolean;
var xRec: Record; var
AllowInsert: Boolean)

OnModifyRecordEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnModifyRecord


Page::<Page Name>, trigger, which is called before a record
'OnModifyRecordEvent', '',
<SkipOnMissingLicense>, is modified in a table.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; var xRec: Record;
var AllowModify: Boolean)

OnNewRecordEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnNewRecord


Page::<Page Name>, trigger, which is called before a new
'OnNewRecordEvent', '',
<SkipOnMissingLicense>, record is initialized.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record; BelowxRec: Boolean;
var xRec: Record)

OnOpenPageEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnOpenPage


Page::<Page Name>, trigger, which is called after a page is
'OnOpenPageEvent', '',
<SkipOnMissingLicense>, initialized and run.
<SkipOnMissingPermission>)]
local procedure MyProcedure(var
Rec: Record)

OnQueryClosePageEvent Trigger Event [EventSubscriber(ObjectType::Page, Executed after the OnQueryClosePage


Page::<Page Name>, trigger, which is called as a page closes
'OnQueryClosePageEvent', '',
<SkipOnMissingLicense>, and before the OnClosePage trigger
<SkipOnMissingPermission>)] executes.
local procedure MyProcedure(var
Rec: Record; var AllowClose:
Boolean)

The following table describes the parameters of the trigger events:

PA RA M ET ER TYPE DESC RIP T IO N

Rec Record The table that used page that raises


the event.

xRec Record The table that used page that raises


the event.
PA RA M ET ER TYPE DESC RIP T IO N

AllowDelete Boolean Specifies whether the OnDeleteRecord


trigger call was successful and the
record can be deleted. If this
parameter is true, the code will be
executed. If this parameter is false,
then the code is not executed.

AllowModify Boolean Specifies whether the OnModifyRecord


trigger call was successful and the
record can be modified. If this
parameter is true, the code will be
executed. If this parameter is false,
then the code is not executed.

BelowxRec Boolean Specifies whether the new record was


inserted after the last record in the
table (xRec).

AllowClose Boolean Specifies whether to the page can


close. If this parameter is true, the
code will be executed. If this parameter
is false, then the code is not executed.

See Also
Events in AL
Publishing Events
Raising Events
Subscribing to Events
Isolated Events
Publishing Events
2/6/2023 • 3 minutes to read • Edit Online

The first phase of implementing an event is publishing the event. Publishing an event exposes it in the
application. It provides hook up points for subscribers to register to the event, and eventually handle the event if
it's raised. An event is published by adding an AL method that is set up as an event publisher.
Business and integration events require that you manually create an event publisher method for each
event that you want to publish. An event publisher method declares the event in the application and
makes it available for subscription. However, it doesn't raise the event. After an event is published, you
can raise it in your application from where event subscribers can react and handle the event.
Trigger events don't require that you create publisher methods. Trigger events are predefined event
publisher methods that are called automatically at runtime. So trigger events are readily available to
subscribers by default.

Creating an event publisher method to publish business and


integration events
You create an event publisher method the same way you create any method in AL. But there are specific
attributes that you set to make it an event publisher. Additionally, an event publisher method has the following
requirements and restrictions that you must follow, otherwise you can't compile your code changes:
An event publisher method can't include any code except comments.
An event publisher method can't have a return value, variables, or text constants.
The following procedure provides an outline of the tasks that are involved in creating an event publisher
method for declaring an event.
To create an event publisher method
1. Decide where you want to include the event publisher method.
You can include an event publisher method in the AL code of any object type, such as codeunit, page, or
table. You can create a new object or use an existing object.

IMPORTANT
If you include the event publisher method in a page object, the page must have a source table. Otherwise, you
can't successfully create an event subscriber method to subscribe to the event.

2. Add an AL method to the object.


If you don't want the event publisher to be raised from other objects than the one defining it, make it a
local method by affixing it with local . The event still remains available to event subscribers from other
objects.
Give the method a name that has the format On[Event], where [Event] is text that indicates what occurred,
such as OnAddressLineChanged .
3. Decorate the method with either the Integration attribute or Business attribute as follows:
[IntegrationEvent(IncludeSender : Boolean, GlobalVarAccess : Boolean)]

or

[BusinessEvent(IncludeSender : Boolean)]

TIP
Use the teventint snippet for an integration event or the teventbus snippet for a business event to get
started.

For more information about integration and business events, see Event Types.
4. Add parameters to the method as needed.
You can include as many parameters of any type as necessary.
Make sure to expose enough information. Parameters enable subscriber methods to add value to the
application. However, don't expose unnecessary parameters that may constrain you from changing or
extending methodically in the future.
You can now add code to the application that raises the event by calling the event publisher method. You can
also create subscriber methods that handle the event when it's raised.

Example
This example creates the codeunit 50100 MyPublishers to publish an integration event. The event is published
by adding the global method called OnAddressLineChanged . The event takes a single text data type parameter.

NOTE
This example is part of a larger, simple scenario where when users change the address of a customer on the page 21
Customer Card , you want to check that the address doesn't include a plus sign (+). If it does, you want to display a
message. To accomplish this, you will publish an event that is raised when the Address field on Customer Card is
changed, and add an event subscriber method to that includes logic that checks the address value and returns a message
to the user if it contains a plus sign. For a complete description of this scenario and all the code involved, see Event
Example.

codeunit 50100 MyPublishers


{
[IntegrationEvent(false, false)]
procedure OnAddressLineChanged(line : Text[100]);
begin
end;
}

The next step is to raise this event in the application. To see an example for how this event is raised, go to Raising
Event Example.

See Also
Raising Events
Subscribing to Events
Events Dynamics 365
Raising Events
2/6/2023 • 2 minutes to read • Edit Online

After an event has been published by an event publisher method, you can modify the application to raise the
event where it is needed. Subscribers of an event will not react on the event until it is raised in the application.
To raise an event, you add logic in AL code of the application to call the event publisher method that declares the
event. The procedure for calling the event publisher method is the same as calling any other method in AL.
When the code that calls the event publisher method is run, all event subscriber methods that subscribe to the
event are run. If there are multiple subscribers, the subscriber methods are run one at a time in no particular
order. You cannot specify the order in which the subscriber methods are called.
If there are no subscribers to the published event, then the line of code that calls the event publisher method is
ignored and not executed.

Snippet support
Typing the shortcut teventsub will create the basic event subscriber syntax when using the AL Language
extension in Visual Studio Code.

TIP
Typing the keyboard shortcut Ctrl+Space displays IntelliSense to help you fill in the attribute arguments and to discover
which events are available to use.

Example
This example uses a page extension object 50100 MyCustomerExt to modify the page 21 Customer Card so
that an event is raised when a user changes the Address field. This example assumes that the event has already
been published by the event publisher method OnAddressLineChanged in a separate codeunit called 50100
MyPublishers .

NOTE
This example is part of a larger, simple scenario where when users change the address of a customer on the page 21
Customer Card , you want to check that the address does not include a plus sign (+). If it does, you want to return a
message to the user. For a description of this scenario and all the code involved, see Event Example.

In the code that follows, the page extension object modifies the OnBeforeValidate trigger of the Customer
Card page to raise the event OnAddressLineChanged which includes the new value of the Address field.
pageextension 50100 MyCustomerExt extends "Customer Card"
{
layout
{
modify(Address)
{
trigger OnBeforeValidate();
var
Publisher: Codeunit MyPublishers;
begin
Publisher.OnAddressLineChanged(Rec.Address);
end;
}
}
}

To learn about how the event used in this example is published, see Publishing Events Example.
The next step would be to subscribe to the event to handle to condition. To see an example of how to subscribe
to this event, see Subscribing to Events Example.

See Also
Publishing Events
Subscribing to Events
Events in AL
Subscribing to Events
2/6/2023 • 5 minutes to read • Edit Online

To handle events, you design event subscribers. Event subscribers determine what actions to take in response to
an event that has been raised. An event subscriber is a method that listens for a specific event that is raised by
an event publisher. The event subscriber includes code that defines the business logic to handle the event. When
the published event is raised, the event subscriber is called and its code is run.
Subscribing to an event tells the runtime that the subscriber method must be called whenever the publisher
method is run, either by code (as with business and integration events) or by the system (as with trigger events).
The runtime establishes the link between an event raised by the publisher and its subscribers, by looking for
event subscriber methods.
There can be multiple subscribers to the same event from various locations in the application code. When an
event is raised, the subscriber methods are run one at a time in no particular order. You can't specify the order in
which the subscriber methods are called.

Creating an event subscriber method


You create an event subscriber method just like other methods except that you specify properties that set up the
subscription to an event publisher. The procedure is slightly different for database and page trigger events than
business and integration events. Business and integration events are raised by event publisher methods in
application code. Trigger events are predefined system events that are raised automatically on tables and pages.
For an explanation about the different types, see Event Types.
To create an event subscriber method
1. Decide which codeunit to use for the event subscriber method.
You can create a new codeunit or use an existing one.
2. Add an AL method to the codeunit.
We recommend that you give the method a name that indicates what the subscriber does, and has the
format [Action][Event]. [Action] is text that describes what the method does. [Event] is the name of the
event publisher method to which it subscribes.
3. Add code to the method for handling the event.
4. Decorate the event subscriber method with the EventSubscriber attribute.

[EventSubscriber(ObjectType::<Event Publisher Object Type>, <Event Publisher Object>, '<Published


Event Name>', '<Published Event Element Name>', <SkipOnMissingLicense>, <SkipOnMissingPermission>)]

Set the arguments according to the following table. For optional arguments, if you don't want to set a
value, use an empty value ( '' ). In this case, the default value, if any, is used.

A RGUM EN T DESC RIP T IO N O P T IO N A L


A RGUM EN T DESC RIP T IO N O P T IO N A L

<Event Publisher Object Type> Specify the type of object that no


publishes the event. This argument
can be Codeunit , Page , Report ,
Table , or XMLPort .

<Event Publisher Object> Specify the object that publishes the no


event. You can set this argument to
the ID, such as 50100 , or the
recommended way is to use the
object name by using the syntax
<Object Type>::"<Object Name>"
, such as
Codeunit::"MyPublishers" , or for
database triggers
Database::"Customer" .

<Published Event Name> Specify the name of method that no


publishes the event in the object
that is specified by the
<Event Publisher Object>
parameter.

<Published Event Element Name> Specifies the table field that the no
trigger event pertains to. This
argument only requires a value for
database trigger events, that is,
when the
<Event Publisher Object Type>
is set to Table and the
<Published Event Name>
argument is a validate trigger event,
such as OnAfterValidateEvent .

<SkipOnMissingLicense> Set to true to skip the event yes


subscriber method call if the user's
license doesn't cover the event
subscriber codeunit. If false , an
error is thrown and the code
execution stops. false is the
default.

<SkipOnMissingPermission> Set to true to skip the event yes


subscriber method call if the user
doesn't have the correct permissions
the event subscriber codeunit. If
false , an error is thrown and the
code execution stops. false is the
default.

TIP
There are a couple of things that can make defining an event subscriber method easier. You can use the
teventsub snippet to get started. Then, typing the keyboard shortcut Ctrl+Space displays IntelliSense to help
you fill the attribute arguments and discover which events are available. Or, use the Shift+Alt+E keyboard
shortcut to look up the event you want to subscribe to and insert the code.
5. Optionally, set the codeunit's EventSubscriberInstance property to specify how the event subscriber
method will be bound to the instance of this codeunit.
For more information, see EventSubscriberInstance Property.

Example 1
This example creates the codeunit 50101 MySubscribers to subscribe to an event that has been published by
the event publisher method called OnAddressLineChanged in the codeunit 50100 MyPublishers . The event is
raised by a change to the Address field on page 21 Customer Card . This example assumes:
The codeunit 50100 MyPublishers with the event publisher method OnAddressLineChanged already exists.
For an example, see Publishing Event Example.
The code for raising the OnAddressLineChanged event has been added to the Customer Card page. For an
example, see Raising Event Example.
The following code creates a codeunit called 50101 MySubscribers that includes an event subscriber method,
called CheckAddressLineOnAddressLineChanged . The method includes code for handling the published event.

codeunit 50101 MySubscribers


{
EventSubscriberInstance = StaticAutomatic;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"MyPublishers", 'OnAddressLineChanged', '', true,


true)]
procedure CheckAddressLineOnAddressLineChanged(line : Text[100]);
begin
if (StrPos(line, '+') > 0) then begin
Message('Can''t use a plus sign (+) in the address [' + line + ']');
end;
end;
}

NOTE
This example is part of a larger, simple scenario where when users change the address of a customer on the page 21
Customer Card , you want to check that the address does not include a plus sign (+). If it does, you want to return a
message to the user. For a description of this scenario and all the code involved, see Event Example.

Example 2
This example achieves the same as example 1, except it subscribes to the page trigger event
OnBeforeValidateEvent on the Address field instead. By using the page trigger, you avoid creating an event
publisher and adding code to raise the event. The event is raised automatically by the system.
codeunit 50101 MySubscribers
{
EventSubscriberInstance = StaticAutomatic;

[EventSubscriber(ObjectType::Page, Page::"Customer Card", 'OnBeforeValidateEvent', 'Address', true,


true)]
local procedure CheckAddressLineOnBeforeValidateEvent(var Rec : Record Customer)
begin
if (StrPos(Rec.Address, '+') > 0) then begin
Message('Can''t use a plus sign (+) in the address [%1]', Rec.Address);
end;
end;
}

See Also
Publishing Events
Raising Events
Event Types
Events in AL
EventSubscriberInstance Property
EventSubscriber Attribute
Isolated Events in AL
2/6/2023 • 2 minutes to read • Edit Online

You can define a business, integration, or internal event to be an isolated event. An isolated event ensures the
event publisher continues its code execution after calling an event. If an event subscriber's code causes an error,
its transaction and associated table changes will be rolled back. The execution continues to the next event
subscriber, or it will be handed back to the event's caller.

How isolated events work


Isolated events are implemented by separating each event subscriber into its own transaction. The transaction is
created before invoking an event subscriber, then committed afterwards. The following diagram illustrates the
flow.

When an event is raised, the platform gets the first event subscriber. When the event is isolated, an isolated
transaction starts, then the event subscriber is invoked. If an error occurs, the transaction is rolled back, and the
flow is repeated for the next event subscriber. Otherwise, the transaction is committed and the flow is repeated
for the next event subscriber.
NOTE
Read-only transactions are allowed to call isolated events directly, but write transactions should explicitly be
committed before invoking an isolated event. Other wise, the isolated event will be invoked like an
normal event, that is, errors inside an event subscriber will cause the entire operation to fail.

Rollback
Only changes done via Modify/Delete/Insert calls on records of type TableType: Normal will be automatically
rolled back. Other state changes, like HTTP calls, variable alterations, changes to single instance codeunit's
members, won't be rolled back.
For example, if an integer variable that's passed by VAR is modified by a failing event subscriber, its changes will
persist.
Extension installation and upgrade
When the operation is installing, uninstalling, or upgrading extensions, isolated events aren't run isolated. The
events run normally instead.
The reason for this behavior is that these operations require that all operations within them are done in one
transaction. So explicit Commit calls can't be made during the operations.

How to define an isolated event


The BusinessEvent, IntegrationEvent, and InternalEvent attributes include the Isolated boolean argument, for
example:

[InternalEvent(IncludeSender: Boolean, Isolated: Boolean)]

To define an isolated event, set the Isolated argument, which is to true , for example:

[InternalEvent(true, true)]

Example
codeunit 50145 IsolatedEventsSample
{
trigger OnRun()
var
Counter: Integer;
cust : Record Customer;
begin
// Precondition: Customer table isn't empty.
if (cust.IsEmpty) then
Error('Customer table is empty.');

MyIsolatedEvent(Counter);

// Code only reaches this point because the above event is isolated and error thrown in
FailingEventSubscriber is caught.
if (Counter <> 2) then
Error('Both event subscribers should have incremented the counter.');

// Post-condition: Customer table hasn't been truncated.


if (cust.IsEmpty) then
Error('Customer table was truncated, failing event subscriber was not rolled back.');
end;

[InternalEvent(false, true)]
local procedure MyIsolatedEvent(var Counter: Integer)
begin
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::IsolatedEventsSample, 'MyIsolatedEvent', '', false,


false)]
local procedure FailingEventSubscriber(var Counter: Integer)
var
cust: Record Customer;
begin
Counter += 1; // Change will persist even after throwing. Only database changes will be rolled back.

cust.DeleteAll(); // Database changes will be rolled back upon error.

Error('Fail!');

// Code below won't be reached!


Counter += 1;
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::IsolatedEventsSample, 'MyIsolatedEvent', '', false,


false)]
local procedure IncreasingEventSubscriber(var Counter: Integer)
begin
Counter += 1;
end;
}

See Also
Publishing Events
Raising Events
Subscribing to Events
Developing Extensions Using the New Development Environment
Discoverability of Events
2/6/2023 • 2 minutes to read • Edit Online

You subscribe to events to extend application and interact with the base application and other extensions. This
topic describes how to discover events that you can subscribe to without writing the code manually. Using the
Event Recorder , you can record the events that are published and raised while performing the actions of your
scenario. For example, record the events raised when you post a purchase order and identify the events that you
need for your extension. You can retrieve the events in the form of AL snippet code and use them in Visual
Studio Code directly.

Using the Event Recorder


You can launch the event recorder session from Dynamics 365 Business Central. It can be accessed in the
following two ways:
In Dynamics 365 Business Central, search for Event Recorder .
In Visual Studio Code, use the Ctrl+Shift+P keys and select the Open Event Recorder command to open
the Event Recorder page in the Dynamics 365 Business Central web client.

NOTE
The event recorder captures all events that are raised in the same session. If the actions performed by the user are in
another session, then the event recorder will not capture them.

How to record events


The following steps describe how to record events when you are on the Event Recorder page.
1. On the Event Recorder page, in the upper right corner, choose Open this page in a new window .
2. Then on the Event Recorder page, choose Record Events , and then choose the Star t button.
3. In the original window, perform all the actions that you want to record while the event recorder session is on.
For example, post a purchase order.
4. After you have performed the actions of your scenario, navigate back to the window that has the Event
Recorder page open and click the Stop button to finish recording.
All the events raised while performing the actions of your scenario are recorded and can be viewed on as
shown below.
5. Choose Get AL Snippet to get the event subscription code in AL. You can use the AL snippet code in
Codeunits to subscribe to those events.

NOTE
The recorded events are not saved. When you refresh the page, the recorded events disappear.

For more information on how to subscribe to events, see Subscribing to Events.

Recorded Events
All the recorded events display in the order they were called. The Event Recorder page provides information on
the events that were raised including the details whether the raised events were trigger events or custom events.
The custom events are either Business Events or Integration Events. For more information, see Event Types.
You can identify the Event types, additionally, you can discover which object types and methods raised the
events with the details like calling methods, object types, and object names. For more information about Events,
see Events in AL.

See Also
Events in AL
Publishing Events
Raising Events
Subscribing to Events
Debugging in AL
Developing Extensions
Event Example
2/6/2023 • 2 minutes to read • Edit Online

This article includes a simple code example to explain how to use Business Central events. The example uses an
event to verify a customer's address. When a user changes the address of a customer on the page 21
Customer Card , an event is used to check that the address doesn't include a plus sign (+). If it does, a message
is displayed in the client. In this example, you'll add code that:
Publishes an event that is raised when the Address field on Customer Card is changed.
Raises the event from the Customer Card page
Subscribes to the event to check the address value and return a message to the user if it contains a plus sign.

// The following code creates codeunit that publishes the `OnAddressLineChanged` event.

codeunit 50100 MyPublishers


{
[IntegrationEvent(false, false)]
procedure OnAddressLineChanged(line: Text[100])
begin
end;
}

// The following code extends the Customer Card page to raise the `OnAddressLineChanged` event
// when the Address field is changed.
pageextension 50100 MyCustomerExt extends "Customer Card"
{
layout
{
modify(Address)
{
trigger OnBeforeValidate();
var
Publisher: Codeunit MyPublishers;
begin
Publisher.OnAddressLineChanged(Rec.Address);
end;
}
}
}

// The following code creates an event subscriber codeunit.


// It declares the `CheckAddressLine` event subscriber that listens for OnAddressLineChanged event.
// The event subscriber displays a message in the client when '+' is used in the **Address** field.

codeunit 50101 MySubscribers


{
//Set the event subscribers to bind automatically to the event
EventSubscriberInstance = StaticAutomatic;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"MyPublishers", 'OnAddressLineChanged', '', true,


true)]
procedure CheckAddressLine(line: Text[100]);
begin
if (STRPOS(line, '+') > 0) then begin
MESSAGE('Can''t use a plus sign (+) in the address [' + line + ']');
end;
end;
}
TIP
This example binds the event subscriber automatically to the event. You can also bind the event subscriber manually, by
setting the EventSubscriberInstance property. For more information, including an example, see EventSubscriberInstance
property.

See Also
Publishing Events
Raising Events
Subscribing to Events
Events Dynamics 365
Walkthrough: Implementing New Workflow Events
and Responses
2/6/2023 • 12 minutes to read • Edit Online

If a business scenario requires a workflow event or a workflow response that is not supported in a Business
Central solution, you must implement it by extending the application code.
In the Workflow page, the workflow administrator creates a workflow by listing the involved steps on the lines.
Each step consists of a workflow event, moderated by event conditions, and a workflow response, customized by
response options. You define workflow steps by filling fields on workflow lines from fixed lists of event and
response values representing scenarios that are supported by the application code. For more information, see
Set Up Workflows in the business functionality content.
The following procedure describes how to add a new workflow event and a new workflow response and then
register the involved object relations, so that the new elements can be used in workflows. You can then share
your code as an app or a per-tenant extension, for example. The workflow administrator can then select the new
workflow event and response from the Workflow page to incorporate them in new or existing workflow steps.

IMPORTANT
To ensure that custom workflow records are upgraded correctly, you must add new workflow events, workflow responses,
and workflow table relations to dedicated extension points, as described in this procedure. During an upgrade to the next
version, the libraries of workflow events, responses, and table relations are removed and then recreated with the latest
content from Microsoft. By adding your custom workflow records using subscriptions to the Microsoft-provided extension
points, you ensure that your custom record library gets recreated after an upgrade.

NOTE
This topic refers to two types of events:
Workflow event: An occurrence in the application that users in the client can select from the Workflow page to define
workflow steps. For more information, see Workflows in Dynamics 365 Business Central in the business functionality
content.
Event: The declaration of the occurrence or change in the application. Workflow events typically subscribe to events.
For more information, see Events in AL.

The development work involved in creating a new workflow event and a related workflow response consists of
the following tasks, as a minimum:
1. Create a workflow event
a. Create a workflow event code that identifies the workflow event
b. Add the workflow event code to the Workflow Event table
c. Create and publish an event that the workflow event subscribes to
d. Raise the event
e. Subscribe to the event and implement the workflow event
2. Create a workflow response
a. Create a workflow response code that identifies the workflow response
b. Add the workflow response code to the Workflow Response table
c. Implement the workflow response
d. Enable that the workflow response can be executed
e. Add a new workflow response option
3. Register workflow event/response combinations needed for the new workflow response
4. Register workflow event hierarchies needed for the new workflow event
5. Creating table relations between entities used when the new workflow event and response are used

NOTE
Data and code samples in this procedure refer loosely to a workflow step of sending a notification when a purchase
header is posted. However, the procedure alone does not result in a complete solution. The purpose of the walkthrough is
simply to illustrate the process.

Workflow event
In this section, we'll create a code to identify the workflow event, add the workflow event to the library, create an
event that the workflow event subscribes to, raise the event, and then subscribe to the event and implement the
workflow event.
Each subsection takes you through the discrete steps.
To create a workflow event code that identifies the workflow event
1. Create a new .al file, such as MyWorkflowEvents.codeunit.al, and add a codeunit that will be used for new
workflow events. Name it to reflect that it is used to identify the new workflow event, such as
MyWorkflowEvents .

2. Add a method in the codeunit. Optionally, use the shortcut tprocedure . Name the method to reflect that
it is used to identify the workflow event, such as MyWorkflowEventCode , and make it take 128 characters of
code as a parameter.

TIP
The terminology can be a bit confusing here. This method is not an AL event. It's a method that declares the workflow
event, and it will subscribe to an AL event that, when triggered, will trigger the workflow event.

Your MyWorkflowEvents.codeunit.al file now looks like this:

codeunit 50101 MyWorkflowEvents


{
procedure MyWorkflowEventCode(): code[128];
begin
end;
}

To add the workflow event code to the Workflow Event table


1. Create another method in the codeunit. Name it to reflect that it is used to add the workflow event to the
library, such as AddMyWorkflowEventsToLibrary .
This method will subscribe to the OnAddWorkflowEventsToLibrary method in the Workflow Event Handling
codeunit in the base application, so you must set the EventSubscriber attribute, and you must add code
that handles the event.
The following code illustrates the new method in the MyWorkflowEvents codeunit:

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Event Handling",


'OnAddWorkflowEventsToLibrary', '', true, true)]
procedure AddMyWorkflowEventsToLibrary()
var
WorkflowEventHandling: Codeunit"Workflow Event Handling";
begin
WorkflowEventHandling.AddEventToLibrary(MyWorkflowEventCode(), Database::"Purchase Header", 'My
workflow event description', 0, false);
end;

To publish an event that the workflow event subscribes to


1. Create another codeunit, such as MyEvents.codeunit.al, and add a method that publishes your event.
Name the method to reflect that it is used as the publisher event, such as OnAfterPostPurchaseHeader .

codeunit 50102 MyEvents


{
[IntegrationEvent(false, false)]
procedure OnAfterPostPurchaseHeader(PurchaseHeader: Record "Purchase Header")
begin
end;
}

Select the event type that is relevant for the workflow event, such as Integration. For more information,
see Event Types.
To raise the event
1. Create an object or an extension object to add the code that will raise the event that triggers the workflow
event, such as the Purch.-Post codeunit.
The following code raises the event by extending the Purchase Order page object in a new file,
MyPurchOrder.PageExt.al .

pageextension 50100 WFW_PurchaseOrder extends "Purchase Order"


{
layout
{
modify(Status)
{
trigger OnBeforeValidate();
var
MyEvents: Codeunit MyEvents;
begin
MyEvents.OnAfterPostPurchaseHeader(Rec)
end;
}
}
}

For more information, see Raising Events.


To subscribe to the event and implement the workflow event
1. Go back to the MyWorkflowEvents.codeunit.al file and add another method in the MyWorkflowEvents
codeunit. Name the new method to reflect that it is used to subscribe to and implement the workflow event,
such as RunWorkflowOnAfterPostPurchaseHeader .

The following code illustrates the new workflow event that subscribes to your previously created event:

[EventSubscriber(ObjectType::Codeunit, Codeunit::MyEvents, 'OnAfterPostPurchaseHeader', '', true, true)]


local procedure RunWorkflowOnAfterPostPurchaseHeader(var PurchaseHeader: Record "Purchase Header")
var
WorkflowManagement: Codeunit "Workflow Management";
begin
WorkflowManagement.HandleEvent(MyWorkflowEventCode, PurchaseHeader);
end;

Another task that you can perform at this point is to specify which filter fields appear in the Workflow Event
Conditions page.
For more information, see Subscribing to Events.
You have now created a new workflow event. Next, we'll create a new workflow response that relates to the
workflow event.

Workflow response
Create a new .al file, such as MyWorkflowResponses.codeunit.al, with code to identify the workflow response,
add the workflow response code to the library, implement the workflow response, and then enable that the
workflow response can be executed.
To create a workflow response code that identifies the workflow response
1. Add a new codeunit that will be used for the new workflow responses. Name it to reflect that it handles
your new responses, such MyWorkflowResponses .
2. Add a method in the codeunit. Name the method to reflect that it is used to identify the workflow
response, such as MyWorkflowResponseCode with a return value of code (128).
To add the workflow response code to the Workflow Response table
1. Add another method in the codeunit that will be the event subscriber. Name it to reflect that it is used to
add the workflow response to the library, such as AddMyWorkflowResponsesToLibrary and set it to subscribe
to the OnAddWorkflowResponsesToLibrary method in the Workflow Response Handling` codeunit.

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Event Handling",


'OnAddWorkflowEventPredecessorsToLibrary', '', false, false)]
local procedure AddWorkflowEventHierarchiesToLibrary(EventFunctionName: Code[128])
begin
end;

2. Add a local variable for the codeunit:

[...]
var
WorkflowResponseHandling: Codeunit "Workflow Response Handling";

3. In the method, write code that registers the response, so that you end up with something like the
following code.
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Response Handling",
'OnAddWorkflowResponsesToLibrary', '', true, true)]
local procedure AddMyWorkflowResponsesToLibrary()
var
WorkflowEventHandling: codeunit "Workflow Event Handling";
begin
WorkflowResponseHandling.AddResponseToLibrary(MyWorkflowResponseCode, Database::"Purchase
Header", 'Send a notification.', 'GROUP 0');
End
end;

NOTE
In the To add a new workflow response option section, you will change the GROUP value to 50100. This way, you'll be
able to see the workflow in action.

The codeunit now looks something like this:

codeunit 50103 MyWorkflowResponses


{
procedure MyWorkflowResponseCode(): code[128];
begin
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Response Handling",


'OnAddWorkflowResponsesToLibrary', '', true, true)]
local procedure AddMyWorkflowResponsesToLibrary()
var
WorkflowResponseHandling: Codeunit "Workflow Response Handling";
begin
WorkflowResponseHandling.AddResponseToLibrary(MyWorkflowResponseCode, Database::"Purchase Header",
'Send a notification.', 'GROUP 0');
end;
}

To implement the workflow response


1. Create another method in the codeunit. Name it to reflect that it is used to implement the workflow
response, such as MyWorkflowResponse , that takes a parameter based on the Purchase Header table.
2. In the method, write code that handles the response, so that you end up with something like the
following code.

procedure MyWorkflowResponse(PurchaseHeader: Record "Purchase Header")


begin
Message('Status change on: %1 %2', PurchaseHeader."Document Type", PurchaseHeader."No.");
end;

To enable that the workflow response can be executed


1. Create another method in the codeunit that subscribes to the OnExecuteWorkflowResponse event on the
Workflow ResponseHandling codeunit. Name it to reflect that it is used to enable the new workflow
response to be executed alongside existing workflow responses, such as ExecuteMyWorkflowResponses .
2. In the event subscriber method, write code that enables the response, so that you end up with something
like the following code.
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Response Handling",
'OnExecuteWorkflowResponse', '', true, true)]
procedure ExecuteMyWorkflowResponses(ResponseWorkflowStepInstance: Record "Workflow Step Instance";
var ResponseExecuted: Boolean; var Variant: Variant; xVariant: Variant)
var
WorkflowResponse: record "Workflow Response";
begin
if WorkflowResponse.GET(ResponseWorkflowStepInstance."Function Name") then
case WorkflowResponse."Function Name" of
MyWFResponseCode:
BEGIN
MyWorkflowResponse(Variant);
ResponseExecuted := TRUE;
END;
END;
end;

You'll update this method in step 8 in the next section.


To add a new workflow response option
1. Create a table extension object that extends table 1523, Workflow Step Argument , such as
MyWorkflowStepArgument.TableExt.al.
2. Add a field that reflects your new response option, such as My New Response Option .

tableextension 50100 WFW_WorkflowStepArgument extends "Workflow Step Argument"


{
fields
{
field(50100; "My New Response Option"; Text[100])
{
}
}
}

3. Create a page extension object that extends page 1523, Workflow Response Options , such as
MyworkflowStepArgument.PageExt.al.
4. Add a group and a control for the new field.

pageextension 50101 WFW_WorkflowResponseOptions extends "Workflow Response Options"


{
layout
{
addlast(content)
{
group(Group50100)
{
Visible = Rec."Response Option Group" = 'GROUP 50100';
ShowCaption = false;

field(MyNewResponseOption; Rec."My New Response Option")


{
ApplicationArea = All;
}
}
}
}
}

Here, the Visibility property of the group is set to "Response Option Group" = 'GROUP 50100' , but you can
set it to another value.
5. Go back to MyWorkflowResponses.codeunit.al and the ´AddMyWorkflowResponsesToLibrary` method.
6. In the method code, change 'GROUP 0' to 'GROUP 50100' .

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Response Handling",


'OnAddWorkflowResponsesToLibrary', '', true, true)]
local procedure AddMyWorkflowResponsesToLibrary()
var
WorkflowResponseHandling: Codeunit "Workflow Response Handling";
begin
WorkflowResponseHandling.AddResponseToLibrary(MyWorkflowResponseCode, Database::"Purchase
Header", 'Send a notification.', 'GROUP 50100');
end;

7. To use the new option in the MyWorkflowResponse method, proceed to add a local parameter and a local
variable and show a message as the response.

local procedure MyWorkflowResponse(PurchaseHeader: Record "Purchase Header"; WorkflowStepInstance:


Record "Workflow Step Instance")
var
WorkflowStepArgument: Record "Workflow Step Argument";
begin
if WorkflowStepArgument.Get(WorkflowStepInstance.Argument) then;

Message('Status change on: %1 %2.\%3', PurchaseHeader."Document Type", PurchaseHeader."No.",


WorkflowStepArgument."My New Response Option")
end;

8. In the ExecuteMyWorkflowResponses method, make the following code change:


Change from this code: MyWorkflowResponse(Variant);

Change to this code: MyWorkflowResponse(Variant,ResponseWorkflowStepInstance);

You have now created the actual workflow event and response. Proceed to perform various tasks that
enable them to be used in workflows.

Register workflow event/response combinations


In this section, you'll add new workflow event/response combinations to table 1509 WF Event/Response
Combination so that they appear correctly in the Workflow Events and Workflow Responses pages.
To register workflow event/response combinations needed for the new workflow response
1. Open the codeunit that you created in the Workflow response section, My Workflow Responses .
2. Create another method in the codeunit that subscribes to the
OnAddWorkflowResponsePredecessorsToLibrary event on the Workflow Response Handling codeunit . Name it
to reflect that it is used to add the workflow event/response combinations to table 1509 WF
Event/Response Combination , such as AddMyWorkflowEventResponseCombinationsToLibrary .
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Response Handling",
'OnAddWorkflowResponsePredecessorsToLibrary', '', false, false)]
local procedure AddMyworkflowEventOnAddWorkflowResponsePredecessorsToLibrary(ResponseFunctionName:
Code[128])
var
MyWorkflowEvents: Codeunit MyWorkflowEvents;
WorkflowResponseHandling: Codeunit "Workflow Response Handling";
begin
Case ResponseFunctionName of
MyWorkflowResponseCode():
WorkflowResponseHandling.AddResponsePredecessor(MyWorkflowResponseCode(),
MyWorkflowEvents.MyWorkflowEventCode());
End
end;

In the method, write code that registers event/response combinations that you want to support in your
application, using a CASE statement, such as the code in the example above.
You can also do this work from the user interface on page 1507 Workflow-Event-Response-
Combinations .

Register workflow event hierarchies


In this section, you'll add new workflow event/event combinations to table 1509 WF Event/Response
Combination so that the workflow events appear in the correct hierarchy in the Workflow Events page.
To register workflow event hierarchies needed for the new workflow event
1. Go back to the MyWorkflowEvents.codeunit.al file with the codeunit that you created in the To create a
workflow event code that identifies the workflow event section, My Workflow Events .
2. Create another method in the codeunit that subscribes to the OnAddWorkflowEventPredecessorsToLibrary
event on the Workflow Event Handling codeunit. Name it to reflect that it is used to add the workflow
event hierarchies to table 1509 WF Event/Response Combination , such as
AddWorkflowEventHierarchiesToLibrary .

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Event Handling",


'OnAddWorkflowEventPredecessorsToLibrary', '', false, false)]
local procedure AddWorkflowEventHierarchiesToLibrary(EventFunctionName: Code[128])
var
WorkflowEventHandling: codeunit "Workflow Event Handling";
begin
Case EventFunctionName of
MyWorkflowEventCode():
//WorkflowEventHandling.AddEventPredecessor(MyWorkflowEventCode(),
WorkflowEventHandling./*[Add your predecessor event code]*/);
;
End
end;

In the method, write code that registers event hierarchies that you want to support in your application,
using a CASE statement, such as the code in the example above.
You can also do this work from the user interface on page 1506 Workflow-Event-Hierarchies .

Create table relations


Workflows events can be executed on different types of records. To keep track of these, you must define
relations between the involved records. In this section, you'll create relationships between the entities that are
used when the new workflow event and response are used.
To create table relations between entities that are processed when the new workflow event and response are
used in workflows
1. Got back to the MyWorkflowEvents.codeunit.al file with the codeunit that you created in the To create a
workflow event code that identifies the workflow event section, My Workflow Events .
2. Create another method in the codeunit that subscribes to the OnAddWorkflowTableRelationsToLibrary
event on the Workflow Event Handling codeunit. Name it to reflect that it is used add workflow table
relations in table 1505 Workflow Table Relation , such as AddWorkflowTableRelationsToLibrary .

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Event Handling",


'OnAddWorkflowTableRelationsToLibrary', '', false, false)]
local procedure AddWorkflowTableRelationsToLibrary()
var
WorkflowSetup: Codeunit "Workflow Setup";
begin
WorkflowSetup.InsertTableRelation(Database::"Purchase Header", 1, Database::"Approval Entry", 2);
end;

In the method, write code that registers table relations that you want to support in your application, such
as the example above.
You can also do this work from the user interface on page 1509 Workflow Table-Relations .
You have now enabled a new workflow scenario by implementing the required workflow event and response in
the application code. The workflow administrator can now select the workflow event and workflow response
from the Workflow page to define new or edit existing workflows. For more information, see Set Up Workflows
in the business functionality content.

See Also
Workflows in Dynamics 365 Business Central
Set Up Workflows
Event Example
Events in AL
Page Extension Object
Table Extension Object
Codeunit Object
Table Object
Get Started with AL
Development and Administration for Dynamics 365 Business Central
Notifications
2/6/2023 • 5 minutes to read • Edit Online

Notifications provide a programmatic way to send non-intrusive information to the User Interface (UI) in the
Web client. Notifications differ from messages initiated by the Message method. Messages are modal, which
means users are typically required to address the message and take some form of corrective action before they
continue working. On the other hand, notifications are non-modal. Their purpose is to give users information
about a current situation, but do not require any immediate action or block users from continuing with their
current task. For example, you could have a notification that a customer's credit limit is exceeded.

Notifications in the UI
In the UI, notifications appear in the Notification bar (similar to validation errors) at the top of the page on
which a user is currently working. The user can then choose to dismiss the notification, which clears it. Or, if
actions are defined on notification, the user can choose one of the actions.
There can be multiple notifications. The notifications appear in chronological order from top to bottom.
Notifications remain for the duration of the page instance or until the user dismisses them or takes action on
them.
Notifications that are defined on sub-pages, for example in parts and FactBoxes, appear in the same
Notification bar.
Validation errors on the page will be shown first.

Notifications in the development environment


By using the Notification and NotificationScope data types and methods in AL, you can add code to send
notifications to users. The following table provides an overview of the available methods. The sections that
follow provide additional information about how to create notifications.

M ET H O D DESC RIP T IO N

Message Specifies the content of the notification that appears in the


UI.

Scope Specifies the scope in which the notification appears.

Send Sends the notification to be displayed by the client.

AddAction Adds an action on the notification.

SetData Sets a data property value for the notification

GetData Gets a data property value from the notification.

Recall Recalls a sent notification.

Creating and sending a notification


You create a notification by using the Message and Send methods. The Message method defines the message
part of the notification. When the Send method is called, the notification is sent to the client and content of the
message is displayed.

MyNotification.Message := 'This is a notification';


MyNotification.Send();

The Send method call should be the last statement in the notification code, after any AddAction or SetData
method calls for the notification instance.

Defining the notification scope


The scope determines where the notification is broadcast in the client. There are two different scopes:
LocalScope and GlobalScope.
A LocalScope notification appears in context of the user's current task, that is, on the page the user is
currently working on. LocalScope is the default.
A GlobalScope notification is not directly related to the current task, and will appear regardless of which
page the user is viewing.

NOTE
GlobalScope is currently not supported. This will be implemented in a future release.

The following code creates a notification in the LocalScope:

MyNotification.Message := 'This is a notification';


MyNotification.Scope := NotificationScope::LocalScope;
MyNotification.Send();

Adding actions on a notification


You add actions on notifications by using the AddAction method. This method provides a way for you to create
interactive notifications. By default, users have the option to dismiss the notifications. However, there might be
cases where you want to provide users with different actions that they can take to address the notification, like
opening an associated page for modifying data.
Conceptually, a notification action calls a method in a specified codeunit, passing the notification object in the
call. The method includes the business logic for handling the action.

MyNotification.Message := 'This is a notification';


MyNotification.Scope := NotificationScope::LocalScope;
MyNotification.AddAction('Action 1',Codeunit::"Action Handler",'RunAction1');
MyNotification.AddAction('Action 2',Codeunit::"Action Handler",'RunAction2');
MyNotification.Send();

The basic steps for adding an action are as follows:


1. Create a global method in a new or existing codeunit. The method must have a Notification data type
parameter for receiving the notification object.
2. Add AL code to the method for handling the action.
3. Specify the codeunit and method in the AddAction method call.
IMPORTANT
You can have more than one action on a notification. A LocalScope notification can have up to 3 actions. A GlobalScope
notification can have up to 2 actions.

Sending data with a notification


You use the SetData and GetData methods to add data to a notification, which is typically needed when actions
are invoked. The SetData method sets, or adds, data to the notification. The data is defined as text in a key-value
pair. With the GetData method, you can then retrieve the data again.
The following code sets data for a notification:

MyNotification.Message := 'This is a notification';


MyNotification.Scope := NotificationScope::LocalScope;
MyNotification.SetData('Created',Format(CurrentDateTime,0,9));
MyNotification.SetData('ID',Format(CreateGuid(),0,9));
MyNotification.AddAction('Action 1',Codeunit::"Action Handler",'RunAction1');
MyNotification.AddAction('Action 2',Codeunit::"Action Handler",'RunAction2');
MyNotification.Send();

The following code gets the data for a notification:

DataValue := MyNotification.GetData('Created');
DataValue := MyNotification.GetData('ID');

Example
This simple example illustrates how notifications work and provides some insight into how you can use them.
This example extends page 42 Sales Order of the CRONUS International Ltd. demonstration database
according to the following:
The code compares a customer's balance with their credit limit. If the balance exceeds the credit limit, a
notification is sent to the client.
The notification includes an action, which has the caption Change credit limit , that opens page 21
Customer Card . This enables the user to increase the credit limit.
To complete the example, follow these steps:
1. Create a page extension object that extends page 42 Sales Order , and add the notification code on the
OnOpenPage trigger.
pageextension 50100 CreditBalanceNotification extends "Sales Order"
{

trigger OnOpenPage()
var
Customer: Record Customer;
CreditBalanceNotification: Notification;
OpenCustomer: Text;
Text003: Label 'The current balance exceeds the credit limit.';
Text004: Label 'Change credit limit';
begin
Customer.Get("Sell-to Customer No.");
if Customer."Balance (LCY)" > Customer."Credit Limit (LCY)" then begin
//Create the notification
CreditBalanceNotification.Message(Text003);
CreditBalanceNotification.Scope := NotificationScope::LocalScope;
//Add a data property for the customer number
CreditBalanceNotification.SetData('CustNumber', Customer."No.");
//Add an action that calls the ActionHandler codeunit, which you define in the next step.
CreditBalanceNotification.AddAction(Text004, Codeunit::"ActionHandler", 'OpenCustomer');
//Send the notification to the client.
CreditBalanceNotification.Send();
end;
end;
}

2. Create a codeunit called ActionHandler for handling the notification action. Add a global method called
OpenCustomer that has a Notification data type parameter called CreditBalanceNotification for
receiving the Notification object, and include the following code on the method:

codeunit 50100 ActionHandler


{
trigger OnRun()
begin

end;

procedure OpenCustomer(CreditBalanceNotification: Notification)


var
CustNumber: Text;
CustNo: Text;
CustRec: Record Customer;
CustPage: Page "Customer Card";
begin
//Get the customer number data from the SetData() call.
CustNo := CreditBalanceNotification.GetData('CustNumber');
// Open the Customer Card page for the customer.
if CustRec.Get(CustNo) then begin
CustPage.SetRecord(CustRec);
CustPage.Run();
end else begin
Error('Could not find Customer: ' + CustNo);
end;
end;
}

See Also
Notification Data Type
Developing Extensions
Get Started with AL
Control Add-in Style Guide
2/6/2023 • 5 minutes to read • Edit Online

This article offers a variety of stylistic definitions that are used throughout Dynamics 365, which you can apply
to your control add-ins to create an experience that complements Dynamics 365.

Introduction
Control add-ins for Dynamics 365 extend a business solution by surfacing contextual functionality alongside
business data. Control add-ins empower users to get more done without costly context switching, no matter
which device they access Dynamics 365 from. Typical uses of control add-ins include unique data visualizations,
surfacing controls from a third party service, or displaying related content from another data source.
Apart from the functionality, an important aspect of creating a control add-in is making sure the control add-in
looks good and blends seamlessly into Dynamics 365. To achieve this, you should follow these basic principles:
Apply similar patterns for command, navigation and presentation of data.
Favor content over chrome
Design for all platforms and input methods.
Make it accessible to all users.
Make it enjoyable and keep users in control.
Dynamics 365 uses a set of specific colors and fonts. You can employ these colors and fonts in your control add-
ins to give it a style that matches the rest of client's user interface.

Colors
Choosing the right color gives the interface visual continuity. Color can be used to convey information to users,
indicate interactivity, give feedback, and more. The following sections describe the colors used in Dynamics 365.
The colors can be used on all aspects of a UI element, such background, border, text, and more.
Main colors
The following colors represent the Dynamics 365 theme main palette.

C O LO R NAME USE H EX VA L UE

Primary color Prominent UI elements and #00B7C3


areas.

Secondary color UI elements and areas in #505C6D


default or subdued state.

Style colors
The following colors are used to express or accent conditions or user activity in the UI. For example, these colors
are used as sentiments, or color indication, on Cues.
C O LO R DESC RIP T IO N H EX VA L UE

Standard #212121

Accent #00B7C3

Strong #212121

Favorable #35AB22

Ambiguous #9F9700

Unfavorable #EB6965

Attention #EB6965

Subordinate #A7ADB6

More palette colors


The following table includes additional colors that you can use in the UI.

C O LO R DESC RIP T IO N H EX VA L UE

Yellow #C9C472

Green #88CE81
C O LO R DESC RIP T IO N H EX VA L UE

Red #E97768

Blue #75B5E7

Light green #59CCB4

Sky 75D8E7

Egg EEEA86

Orange #E89E63

Violet #DBBDEB

Teal #39B294

Grass #73BA5A

Scarlet #E65E6D

Chart colors
The following table describes the colors used in charts.
C O LO R DESC RIP T IO N H EX VA L UE

- #505C6D

- #008089

Primary color #00B7C3

Yellow #C9C472

Red #E97768

Blue #75B5E7

Light green #59CCB4

Sky 75D8E7

Egg EEEA86

Violet #DBBDEB

Teal #39B294

Grass #73BA5A
Applying colors
To apply a color scheme to the control add-in, you specify CSS rule-sets that use the following properties:

P RO P ERT Y DESC RIP T IO N

color Specifies font color.

background-color Specifies background colors.

border-color Specifies Border colors.

For example, to change the background of a part of your UI to use the Secondary (#505C6D) color, write the
following CSS:

.my-ui-part {
background-color: #505C6D;
}

If you want to change the text color of a caption to the Primary (#00B7C3) color, use the following CSS:

.my-caption {
color: #00B7C3;
}

Typography
The main goal of typography is to provide clean and readable text in the user interface. Similar to colors,
typography can also be used to convey or communicate conditions to the user.
Font Families
Dynamics 365 uses the following font families to specify the typeface and weight for text elements, such as
headings, captions, messages, and so on:

EXA M P L E NAME VA L UE

Segoe UI "Segoe UI", "Segoe WP", Segoe,


device-segoe, Tahoma, Helvetica,
Arial, sans-serif

Segoe UI Light "Segoe UI Light", "Segoe WP


Light", device-segoe-light,
"Segoe WP Semilight", "Segoe
UI", "Segoe WP", Segoe, Tahoma,
Helvetica, Arial, sans-serif

Segoe UI Semilight "Segoe UI Semilight", "Segoe WP


Semilight", device-segoe-
semilight, "Segoe UI", "Segoe
WP", Segoe, Tahoma, Helvetica,
Arial, sans-serif

Segoe UI Semibold "Segoe UI Semibold", "Segoe WP


Semibold", device-segoe-
semibold, "Segoe UI", "Segoe
WP", Segoe, Tahoma, Helvetica,
Arial, sans-serif
Sizes
Dynamics 365 uses the following font sizes for text. The same font family on different clients may apply different
sizes.

EXA M P L E NAME VA L UE

largest-plus-font-size 37.5pt

largest-font-size 30pt

large-plus-font-size 22.5pt

large-font-size 18pt

medium-plus-font-size 15pt

medium-font-size 13.5pt

small-plus-font-size 12pt

small-font-size 10.5pt

smallest-font-size 9pt

Applying Font Families and Sizes


To apply fonts and sizes to text elements in the UI, you need specify the following CSS properties:
Font family. use property font-family .
Font size. use property font-size .
For example, to change a UI element for the Web client to use the font family Segoe UI Light and the size Small
(10.5pt), write the following CSS:
.my-ui-part {
font-family: "Segoe UI Light", "Segoe WP Light", device-segoe-light, "Segoe WP Semilight", "Segoe UI",
"Segoe WP", Segoe, Tahoma, Helvetica, Arial, sans-serif;
font-size: 10.5pt;
}

IMPORTANT
To ensure that the correct fonts are used on devices, do not omit fonts or change the order of the fonts.

Example
This examples illustrates how to use CSS to style a simple HTML UI part of a control add-in. The example
includes three UI controls, as shown in the following HTML code:

<div class="addin">
<div class="control">
<div class="caption">Name:</div>
<div class="value">
<input type="text" name="name">
</div>
</div>

<div class="control">
<div class="caption">Surname:</div>
<div class="value">
<input type="text" name="name">
</div>
</div>

<div class="control">
<div class="submit">Submit</div>
</div>
</div>

The following is CSS code for styling the controls, including padding, background colors, and fonts:
.addin {
padding: 1em;
background-color: #505C6D; /* Sets the background color to "Secondary" */
}

.addin .control {
border-color: #00B7C3; /* Sets the border color to "Primary" */
}

.addin .control .caption {


color: #00B7C3; /* Sets the captions to "Primary" */

/* Segoe UI Light, small */


font-family: "Segoe UI Light", "Segoe WP Light", device-segoe-light, "Segoe WP Semilight", "Segoe UI",
"Segoe WP", Segoe, Tahoma, Helvetica, Arial, sans-serif; /* Sets the font of the caption to ""Segoe UI
Light" */
font-size: 10.5pt;
}

.addin .control .value {


color: #008089; /* Tertiary shade 2 */

/* Segoe UI, medium */


font-family: "Segoe UI", "Segoe WP", Segoe, device-segoe, Tahoma, Helvetica, Arial, sans-serif;
font-size: 12pt;
}

.addin .control .submit {


color: white; /* Sets the caption text to "white" */
background-color: #00B7C3; /* Sets the background to "Primary */

/* Segoe UI Semibold, medium */


font-family: "Segoe UI Semibold", "Segoe WP Semibold", device-segoe-semibold, "Segoe UI", "Segoe WP",
Segoe, Tahoma, Helvetica, Arial, sans-serif;
font-size: 12pt;
text-transform: uppercase; /* Sets the caption to use all uppercase letters */
}

See Also
Control Add-in Best Practices
Control Add-In Performance Best Practices
2/6/2023 • 2 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave 1 and later

When developing control add-ins it's important to provide the best possible experience, as well as performance
so that users can maintain their productivity without interruption. With version 20.0 of Business Central the
client, if it detects a slow, or unhealthy control add-in, will present the user with a warning equivalent to the
following.

The dialog can be closed by the user, but will appear again if the control add-in continues to run slowly. To
ensure that the client is responsive and fast, the non-responsive or non-performant control add-in will result in
continuous warnings, and if the problem persists the control add-in communication is throttled depending on
the volume of communication with the Business Central service. If the volume of requests to Business Central
does not decrease, the service actively rejects incoming calls, resulting in some or all of the control add-in not
functioning.

Code examples
Bad code example
The following example illustrates code that is problematic and might cause performance issues because the
trigger is invoked no matter if the previous calls are completed.

function invokeALTriggerTheWrongWay() {
// Invoke the trigger every 10 seconds, ignoring
// whether the previous call has completed
window.setTimeout(() => {
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(
"MyTrigger",
arguments,
false);

invokeALTriggerTheWrongWay();
},
10000);
}

Good code example


The following example illustrates the right implementation where the trigger is invoked only when the previous
call is completed.
function invokeALTriggerTheRightWay() {
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(
"MyTrigger",
arguments,
false,
() => {
// Invoking the AL trigger has completed, invoke
// the AL trigger again in 10 seconds
window.setTimeout(() => {
invokeALTriggerTheRightWay();
},
10000);
},
() => { /* error handling and perhaps retrying */ });
}

See also
Control Add-In Resiliency
InvokeExtensibilityMethod Method
GetEnvironment Method
Add Power BI Report Parts to Pages
2/6/2023 • 7 minutes to read • Edit Online

APPLIES TO: Business Central 2022 release wave (v21) and later. For earliers versions, see Adding Power BI
Report Parts to Pages (Legacy).

Business Central integrates with Microsoft Power BI, enabling users to create Power BI reports based on
Business Central data. Users can view the reports from their Power BI workspaces, but also from the Business
Central client. For an overview about Power BI integration, see Business Central and Power BI.
Displaying a Power BI report in a Business Central page requires the page includes a Power BI Repor t part.
This part makes the connection to the Power BI Service, and lets users choose which report to display. Business
Central comes equipped with several pages that already include the Power BI Repor t part. For a list of these
pages, see Power BI FAQ.

Power BI Report part framework


The Business Central base application has many remote that provide the framework for Power BI integration.
You'll find these objects in the Applications\BaseApp\Source\Base Application.Source.zip\Power BI
framework folder of the installation media (DVD). But specifically, the main object for displaying Power BI
Repor t part on role centers and other pages is page 6325 "Power BI Embedded Report Part".
On roles centers, you'd typically use the part to display reports related to the user's role and daily activities. In
FactBoxes, you'd typically use it on list type pages to show reports related to selected records. A page can
include more than one Power BI Report part.
The "Power BI Embedded Report Part" page exposes several methods for controlling when the Power BI
Repor t part appears and the data it contains. The next sections include code examples of how to extend pages
with the Power BI Repor t part. You can also read more in the BCTech repo.

Add a Power BI Report part


To add a Power BI part to a page, you add a part control to the hosting page and associate it with page 6325
"Power BI Embedded Report Part" using the following syntax:

part(<part_name>; "Power BI Embedded Report Part")


{
}

For example, the following code adds a Power BI Report part to the Team Member Role Center page by using
a page extension.
pageextension 50101 TeamMemberRCPwrBiExt extends "Team Member Role Center"
{
layout
{
addfirst(rolecenter)
{
// Add the Power BI Report part on the role center page
part(PowerBIReportPart"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
}
}
}
}

The following code adds a Power BI Report part to the Sales Invoices List page by using a page extension.

pageextension 50100 SalesInvoicesListPwrBiExt extends "Sales Invoice List"


{
layout
{
addfirst(factboxes)
{
// Add the Power BI Report FactBox page as the first part in the
// FactBox area on the Sales Invoice List page
part("Power BI Report FactBox"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
}
}
}
}

Add a Power BI Report part that updates data based on selected


record
With Power BI Report parts in FactBoxes of list and card pages, in many cases you'll want the report to update to
display data that pertains to selected record on the page. You can implement this capability by using the
SetCurrentListSelection method of page 6325 "Power BI Embedded Report Part". The method has the
following signature:

Page."Power BI Report FactBox Part".PAGE.SetCurrentListSelection(InputSelection: Variant)

The InputSelection variant specifies the table field that uniquely identifies records in the list page. This field
should resolve to the primary key of the source table.
Example 1
This example extends the Sales Invoices page to include a Power BI Report part and uses the
SetCurrentListSelection method to use the update data in the report based on the primary key No. of the
Sales Invoice table.
pageextension 50100 SalesInvoicesListPwrBiExt extends "Sales Invoice List"
{
layout
{
addfirst(factboxes)
{
part("Power BI Report FactBox"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
}
}
}

trigger OnAfterGetCurrRecord()
begin
// Gets data from Power BI to display data for the selected record in the list
// based on the primary key, in this case the "No." field.
CurrPage."Power BI Report FactBox".PAGE.SetCurrentListSelection(Rec."No.");
end;
}

Add multiple Power BI Report parts


If you want to add more than one Power BI Report part to a page, where each part can display different reports,
you have to assign each part a context keyword. There are two ways to assign a context keyword, depending on
the page type.
Use SubPageView property
For role centers and other page types, you can use the SubPageView property of the part control that contains
the Power BI report part. In this case, the syntax for the adding a Power BI Report part is:

part(<part_name>; "Power BI Embedded Report Part")


{
SubPageView = where(Context = const('<context_keyword>'));
}

For example, suppose you wanted to add two Power BI Report parts to the Team Member Role Center page.
In this case, you could use the following code:
pageextension 50101 TeamMemberRCPwrBiExt extends "Team Member Role Center"
{
layout
{
addfirst(rolecenter)
{
part(PowerBIReportPart; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
SubPageView = where(Context = const('TeamMemberReportsPart1'));
}
part(PowerBIReportPart2; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
SubPageView = where(Context = const('TeamMemberReportsPart2'));
}
}
}
}

You can do the same for FactBoxes on list and card type page. For example, suppose you wanted to add two
Power BI Report parts in the FactBox of the Sales Invoices List . In this case, you could use the following code:

pageextension 50100 SalesInvoicesListPwrBiExt extends "Sales Invoice List"


{
layout
{
addfirst(factboxes)
{
part("Power BI Report FactBox 1"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports 1';
SubPageView = where(Context = const('DetailedSalesInvoiceReports1'));

}
part("Power BI Report FactBox 2"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports 2';
SubPageView = where(Context = const('DetailedSalesInvoiceReports2'));
}
}
}

trigger OnAfterGetCurrRecord()
begin
CurrPage."Power BI Report FactBox 1".PAGE.SetCurrentListSelection(Rec."No.");
CurrPage."Power BI Report FactBox 2".PAGE.SetCurrentListSelection(Rec."No.");
end;
}

Use SetPageContext method


For list and card type pages, another way to assign context keywords is to call the SetPageContext method of
the "Power BI Embedded Report Part" page.

procedure SetPageContext(InputContext: Text)

By calling SetPageContext , you can get the same results as you do with the SubPageView property. For example:
pageextension 50100 SalesInvoicesListPwrBiExt extends "Sales Invoice List"
{
layout
{
addfirst(factboxes)
{
part("Power BI Report FactBox 1"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports 1';

}
part("Power BI Report FactBox 2"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports 2';
}
}
}

trigger OnOpenPage()
begin
CurrPage."Power BI Report FactBox 1".PAGE.SetPageContext('DetailedSalesInvoiceReports1');
CurrPage."Power BI Report FactBox 2".PAGE.SetPageContext('DetailedSalesInvoiceReports2');

trigger OnAfterGetCurrRecord()
begin
CurrPage."Power BI Report FactBox 1".PAGE.SetCurrentListSelection(Rec."No.");
CurrPage."Power BI Report FactBox 2".PAGE.SetCurrentListSelection(Rec."No.");
end;
}

Display same set of Power BI reports on different pages


Suppose you want set up Power BI Repor t parts on different pages, where the parts have the following
behavior:
They show the same report selected by the user on all pages. When the user switches to another report on
one page, it will switch on all pages.
When a report is enabled or disabled in the Power BI Repor t part on one page, it's also enabled or disabled
in the parts on other pages.
To configure this functionality, you give each Power BI Repor t part on the different pages the same context
keyword. In other words, use the same values for the SubPageView property for the parts on all pages:

SubPageView = where(Context = const('<context_keyword>'))

Example 2
Suppose you want to display the same reports on the Sales Invoices page and Sales Orders page. In this
case, you could use the following line of code in both the Sales Invoices and Sales Orders pages, where
Sales is the common context identifier:
pageextension 50100 SalesInvoicesListPwrBiExt extends "Sales Invoice List"
{
layout
{
addfirst(factboxes)
{
part("Power BI Report FactBox"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
SubPageView = where(Context = const('sales'));
}
}
}

trigger OnAfterGetCurrRecord()
begin
CurrPage."Power BI Report FactBox".PAGE.SetCurrentListSelection(Rec."No.");
end;
}

pageextension 50101 SalesOrdersPwrBiExt extends "Sales Orders"


{
layout
{
addfirst(factboxes)
{
part("Power BI Report FactBox"; "Power BI Embedded Report Part")
{
ApplicationArea = Basic, Suite;
Caption = 'Power BI Reports';
SubPageView = where(Context = const('sales'));
}
}
}

trigger OnAfterGetCurrRecord()
begin
CurrPage."Power BI Report FactBox".PAGE.SetCurrentListSelection(Rec."No.");
end;
}

Limitations and behavior notes


The SubPageView property for the Power BI parts only supports constant values, not filters.
If you use both the SubPageView property and the SetPageContext method for specifying a context at the
same time, the SetPageContext value will overwrite the value specified in the SubPageView property.
Dynamically changing the context (for example, by calling SetPageContext in the OnAfterGetCurrRecord ) isn't
recommended and could lead to unexpected results.
Role center pages have no triggers, which means there's no way to call the SetPageContext method. As a
consequence, any Power BI part in the role center would have the same context: the current user's
profile/role.

See Also
Get Started with AL
Adding a FactBox to a Page
Pages Overview
Publishing and Installing an Extension
Rules and Guidelines for AL Code
2/6/2023 • 4 minutes to read • Edit Online

This page defines the rules and guidelines to follow when writing AL code in an extension package for Dynamics
365 Business Central. The rules and guidelines are grouped according to two importance levels: critical errors
that must be resolved, and important errors that should be resolved. Errors that are not resolved must include
an explanation and justification for the error.

Critical errors
Code uses encryption key functions such as IMPORTENCRYPTIONKEY, EXPORTENCRYPTIONKEY,
CREATEENCRYPTIONKEY, and DELETEENCRYPTIONKEY. (It is fine to use the ENCRYPT and DECRYPT
methods.)
Code uses ASSERTERROR.
External data connections do not properly handle sensitive data.
It does not encrypt sensitive table data. (i.e. credit card info, passwords, etc.).

Important errors
Temporary files are not cleaned up after use.
Code uses codeunits that require printers to be selected.
Code uses a specific time zone or locale.

Common pitfalls
To help you save time, we're sharing a list of the top 15 common pitfalls that regularly lead to app validation
failures.
1. Prefix/Suffix missing
One of the app requirements is for you to reserve a prefix/suffix for your app. This is needed to ensure a
healthy app ecosystem by avoiding collision amongst apps. This common failure occurs due to not
setting your prefix/suffix in some or all required places. For more information, see Benefits and
Guidelines for using a Prefix or Suffix.
2. DataClassification missing or set incorrectly
Due to GDPR requirements, fields of field class Normal must use the DataClassification property, and its
value must be different from ToBeClassified. This applies to fields in tables and table extensions. Use the
AppSourceCop tool for detecting this.
3. Required translation files missing
There are many countries today that where Dynamics 365 Business Central is available, and that you can
support as well with your app. For specifying additional languages, we no longer support Caption ML.
You must use xliff translation files instead. For more information, see Working with Translation Files.
Microsoft provides a free translation tool that you can access from https://lcs.dynamics.com. To support a
specific country, you must include a translation file per for each language code. For example, to support
Switzerland, you must provide fr-CH, de-CH, and it-CH.
4. Missing permission sets
Your app must provide one or more permission sets so that users can use your app's functionality. Your
app must never require the SUPER permission set.
5. Permission errors
For your app to be a good citizen in Dynamics 365 Business Central, permission errors must not appear
unless it is a necessary reason for showing the error.
It is acceptable to throw an error to a user that does not have your permission set marked and tries to
access your page object. It is not acceptable to throw an error to that same user trying to access Business
Central pages in the base application, or to throw an error to a user who is not trying to access your app's
functionality.
6. Missing application area tagging
Tag in which part your app participates. Pages, controls, actions, and fields will not appear in Dynamics
365 Business Central if the Application Area property has not been set.
7. Usage Category not set
You enable a page or report to be available through search in Dynamics 365 Business Central by using
the UsageCategory property. For more information, see Using Tell Me to Find Features and Information.
8. OnCompany procedure
Due to their performance impact, OnBeforeCompanyOpen and OnAfterCompanyOpen cannot be used.
For more information, see Replacing OnBeforeCompanyOpen and OnAfterCompanyOpen.
9. Upgrade procedures
Make sure that your app can be upgraded properly. For more information, see Upgrading extensions.
10. Profiles
Do not insert into the Profile table. Use the Profile object instead.
11. App file not properly code signed
Your app file must be digitally signed with a certificate from a third-party certification authority trusted
by Windows.
12. You tested your app on an obsolete Dynamics 365 Business Central version (or never even tested it)
Make sure that your app is properly tested on the correct version. For more information, see Current
Build - Developing for Dynamics 365 Business Central on the Collaborate site.
13. You tested using SUPER permissions
You tested your app, but your user had SUPER permissions. This can hide critical errors. You must test
with a user that doesn't have the SUPER permissions. The user must have the ESSENTIAL license. For
more information, see Testing your Extension.
14. User scenario document unclear
Our validation team is testing your app functionality manually, so we need to be able to understand the
core functionality of your app. If your user scenario document is missing important details that are
needed for us to properly walk through your app's setup and usage scenarios, we cannot validate your
app successfully. For more information, see User Scenario Documentation.
15. The .json file is incorrect
There are many values in the app.json file that may not be mandatory to compile your app, but are
mandatory for your app to be in AppSource. For example, your app cannot be published to a production
tenant if the target value is set to OnPrem. It must be set to Cloud. For information, see JSON Files.

See Also
Best Practices for AL Code
Checklist for Submitting Your App
Best Practices for Deprecation of AL Code
2/6/2023 • 2 minutes to read • Edit Online

This article provides guidelines that describe how code in the Base App is obsoleted. The article describes some
best practices that Microsoft is using for obsoleting code, and is meant as a non-enforced guidance and best
practice. You can use this article as an inspiration on how to set up a best practice for your own code. For
obsoleting code, preprocessor statements in AL can be used. For more information, see Directives in AL.

Obsoleting Code
When we obsolete code, we:
Add the preprocessor statements #if , #else , and #endif surrounding the code to be obsoleted.
Use one of the following preprocessor symbols, where the pattern is CLEAN<Version> , such as CLEAN15 ,
CLEAN16 , CLEAN17 , and CLEAN18 .

NOTE
These symbols are not shipped with the product.

The version to use in the symbol matches the <major> of the ObsoleteTag . For example:
If a method is to be removed, then we're using #if not

#if not CLEAN18


[Obsolete('Replaced by SetParameters().', '18.0')]
procedure SetParams(NewAnalysisArea: Option Sales,Purchase,Inventory; NewReportName:
Code[10]; NewLineTemplateName: Code[10]; NewColumnTemplateName: Code[10])
begin
SetParameters("Analysis Area Type".FromInteger(NewAnalysisArea), NewReportName,
NewLineTemplateName, NewColumnTemplateName);
end;
#endif

If an action is to be removed, then we're also using #if not

#if not CLEAN17


action("Social Listening Setup")
{
ApplicationArea = All;
Caption = 'Social Engagement Setup';
RunObject = page "Social Listening Setup";
Visible = false;
ObsoleteState = Pending;
ObsoleteReason = 'Microsoft Social Engagement has been discontinued.';
ObsoleteTag = '17.0';
}
#endif

If a table or table field is to be removed, then we'll use #if #else #endif
table 1808 "Aggregated Assisted Setup"
{
Access = Internal;
Caption = 'Aggregated Assisted Setup';
#if CLEAN16
ObsoleteState = Removed;
ObsoleteTag = '17.0';
#else
ObsoleteState = Pending;
ObsoleteTag = '16.0';
#endif
ObsoleteReason = 'Data available in Assisted Setup already- extensions also register in
the same table.';

field(11701; "Bank Account No."; Text[30])


{
Caption = 'Bank Account No.';
Editable = false;
#if CLEAN18
ObsoleteState = Removed;
ObsoleteTag = '18.0';
#else
ObsoleteState = Pending;
ObsoleteTag = '17.0';
#endif
ObsoleteReason = 'Moved to Core Localization Pack for Czech.';
}

If a table is to be marked as Temporary , then we'll use #if #else #endif

table 5503 "Acc. Schedule Line Entity"


{
Caption = 'Acc. Schedule Line Entity';
// TableType = Temporary;
#if CLEAN17
TableType = Temporary;
#else
ObsoleteState = Pending;
ObsoleteReason = 'Table will be marked as TableType=Temporary. Make sure you are not using
this table to store records';
ObsoleteTag = '17.0';
#endif

In order to have the compiler take the new ‘clean’ code path, the symbols must be defined. The symbols are
defined in the app.json file with the following setting. For more information, see JSON Files.

"preprocessorSymbols": [ "CLEAN15", "CLEAN16", "CLEAN17", "CLEAN18" ]

IMPORTANT
A best practice is to change this locally to make sure everything compiles, run tests locally, and submit test jobs.

Fixing code when objects are removed


If an action or other code element points to a now removed object, then the guidance is to:
Ensure that the action is obsoleted.
Add preprocessor statements to fix the issue.
If code points to an obsoleted method, then use directives to put in the fixed code.
If code points to an obsoleted table/field, then use directives to put in the fixed code.

See Also
AL Development Environment
Directives in AL
Microsoft Timeline for Deprecating Code in Business Central
ObsoleteTag Property
ObsoleteState Property
ObsoleteReason Property
Obsolete Attribute
Benefits and Guidelines for using a Prefix or Suffix
2/6/2023 • 4 minutes to read • Edit Online

In your extension, the name of each new application object (table, page, codeunit), must contain a prefix or suffix.
This rule applies to all objects. You can use the Caption values for what you decide to display to the user. When
you modify a core Dynamics 365 object using a table extension or a page extension, the prefix/suffix must be
defined at the control/field/action/group level.

Benefits
The use of affixes reduces name collisions with objects defined in other extensions.
Environments that have extensions with name collisions can experience issues when deploying new extensions,
when upgrading the environment, or when creating a sandbox as a copy of the current environment (for
production environments).

General rules
The prefix/suffix must be at least 3 characters
The object/field name must start or end with the prefix/suffix
If a conflict arises, the one who registered the prefix/suffix always wins
For your own objects, you must set the prefix/suffix at the top object level
For pages/tables/enums/reports/permissionsets in the base application or other apps that you extend, you
must set the prefix/suffix at the top object level and also at the
control/field/action/procedure/values/dataitem/column level
Use the AppSourceCop tool to find all missing prefixes and/or suffixes. Configuration options for this tool
can be found here. The Rules section explains the different checks that the analyzer will do. For prefix/suffix
detection, refer to the Configuration section. It explains how to set your affixes in the AppSourceCop.json file.

Affixes requirements for extensions


For AppSource extensions

IMPORTANT
The use of affixes for object names is required for AppSource submissions as part of the Technical Validation Checklist.

In order to meet the requirements for the AppSource technical validation, you must have a 3 letters affix
registered for your extension publisher and you must use the affix in your extension.
If you do not have any affixes registered yet, contact us at d365val@microsoft.com and provide us with the
following information to reserve the prefix/suffix of your choosing:
Your MPN ID,
The publisher name that you will use in your extensions (in the app.json file),
You must provide at least 5 affix suggestions. Each affix must be exactly 3 characters.
NOTE
Affixes are not case-sensitive, which means that for example "ABC", "abc", and "AbC" are treated as the same affix.
Providing both "ABC" and "abc" counts as only one of your suggestions.

Note, that you are not required to change any already registered affixes; you can continue using these affixes.
The guidelines above only apply to new registrations.
For per-tenant extensions
Per-tenant extensions are not required to use a prefix or suffix, but we strongly recommend that you do so. You
can use pte as prefix or suffix to avoid conflicts with AppSource apps or base objects.

NOTE
If your per-tenant extension causes a conflict with a new object in the base application or an updated AppSource app,
then the per-tenant extension will be required to make the change.

Examples of objects with affixes


Declare your objects with a prefix or suffix as shown in the following examples.
Table

table 70000000 MyPrefixSalesperson


{
Caption = 'Sales Person';
}

table 70000001 SalespersonMySuffix


{
Caption = 'Sales Person';
}

Page

page 70000000 MyPrefixSalesperson


{
Caption = 'Sales Person';
}

page 70000001 SalespersonMySuffix


{
Caption = 'Sales Person';
}

Page extension objects


actions
{
addafter(ApprovalEntries)
{
action(MyPrefixVacation)
{
Caption = 'Vacation';
}
}
}

actions
{
addafter(ApprovalEntries)
{
action(VacationMySuffix)
{
Caption = 'Vacation';
}
}
}

Codeunit

codeunit 70000000 MyPrefixSalesperson

codeunit 70000001 SalespersonMySuffix

Examples – per-tenant extension


Let's say that you're creating a per-tenant extension, myext and you want to future-proof the naming by
applying the prefix or suffix pte, which you are not required to register.
Let's look at some examples:

P REF IXES SUF F IXES

pte-myext-salespersoncode salespersoncode-myext-pte

pte_myext_salespersoncode salespersoncode_myext_pte

pte myext salesperson code salesperson code myext pte

pteMyExtSalesPersonCode SalesPersonCodeMyExtPte

Examples - AppSource app


Alternatively, let's say that your company is Fabrikam, and you're building an app called Rentals. First thing, you
email d365val@microsoft.com and register fab as your company affix.
A registered affix must be 3 letters, no more, no less, and you must provide the publisher name, which you will
be using in app.json when you apply for an affix.
Once you get confirmation from Microsoft, you are free to use object and field names that start with fab or end
with fab. Here are some examples:

P REF IXES SUF F IXES

fab-salespersoncode salespersoncode-fab

fab_salespersoncode salespersoncode_fab

fab salespersoncode salespersoncode fab

FabSalesPersonCode SalesPersonCodefab

At Fabrikam, another team is building another app, so you request a special affix for your app so that the two
Fabrikam apps can be kept apart. In this scenario, you do not have to register anything with Microsoft, as long as
you do this with your company affix. Here are some examples:

P REF IXES SUF F IXES

fab-rentals-salespersoncode salespersoncode-rentals-fab

fab_rentals_salespersoncode salespersoncode_rentals_fab

fab rentals salesperson code salesperson code rentals fab

FabRentalsSalesPersonCode SalesPersonCodeRentalsfab

In this scenario, your AppSourceCop.json configuration will specify fab-rentals and rentals-fab as values for
mandatoryaffixes , even though only fab was registered with Microsoft.

See Also
Checklist for Submitting Your App
Rules and Guidelines for AL Code
Instrumenting an Application for Telemetry
2/6/2023 • 2 minutes to read • Edit Online

This article describes how you can implement custom telemetry signals in your application for emitting
telemetry data. This data can then be collected and visualized for analyzing the application against the desired
business goals, troubleshooting, and more.

Telemetry overview
One aspect of event logging is the data collection about the working and deployment infrastructure of an
application to diagnose conditions and troubleshoot problems that affect its operation and performance. For
example, this type of event logging includes Business Central Server events and trace events like SQL and AL
method (function) traces.
Another aspect of logging is telemetry, which is the collection of data about how your application works in
production. Telemetry can tell you about specific activities that users perform within the application in the
production environment. Telemetry also helps troubleshooting in those instances where you aren't able to
reproduce the conditions experienced by the user or have no access to the user's environment. Telemetry can be
divided into different categories, like: telemetry for engineering, telemetry about the business, telemetry for
customers.

Creating custom telemetry signal


There are two different resources where telemetry trace signals can be sent for monitoring and analyzing: Event
Log and Microsoft Azure Application Insights. By default, the Business Central application is instrumented to
emit several system telemetry trace signals to these destinations. Custom telemetry trace signals enable you to
send telemetry data from anywhere in the application code to either of these destinations.
The procedure for creating custom telemetry signals is different for each resource. Your choice might also
depend on whether you're developing for Business Central online or on-premises.

RESO URC E DESC RIP T IO N O N L IN E O N - P REM ISES M O RE IN F O RM AT IO N


RESO URC E DESC RIP T IO N O N L IN E O N - P REM ISES M O RE IN F O RM AT IO N

Application Insights Create custom See...


telemetry signals
that are sent to an
Application Insights
resource in Azure.
Application Insights
is a service hosted
within Azure that
gathers telemetry
data for analysis and
presentation.

Extension developers
can specify whether
the signal is only sent
to the extension
publisher or also to
the VAR partner
telemetry resource.

You create these


custom trace signals
by using the
LOGMESSAGE
method in the code.

Event Log Create custom See...


telemetry trace
signals that are sent
to the Event Log of
the Business Central
Server machine. You
create these custom
trace signals by using
the SENDTRACETAG
method in the code.

NOTE
Using Application Insights is recommended.

See Also
Monitoring and Analyzing Telemetry
Monitoring Business Central Server Events
Testing your Extension
2/6/2023 • 4 minutes to read • Edit Online

Several key things lead to your Dynamics 365 Business Central extension passing the Microsoft validation
process. However, one of the most important checks you can do is to take the time and test your extension
before submitting it for validation. This allows you to catch some of the basic errors that could lead to validation
failures. The following list calls out key points, and the sections below provide more context.
Always test in a Dynamics 365 Business Central online environment. If you test in an on-premises
deployment, you might miss errors that would be seen online.
Ensure that your extension can be published without code signing errors. You must not use the
-skipverification flag.
The extension should be able to be installed without errors.
If you are using the Assisted Setup , ensure that you can use your wizard to completion without errors.
Walk through the setup and usage of your extension to verify it works as expected (remember to test as a
user that does not have SUPER permissions ).
Check that you can uninstall and unpublish your extension without any errors.
Make sure you can republish and reinstall your extension without any errors.

Use the correct Dynamics 365 Business Central version


Use Docker for your development and testing. At least, run your full test in Dynamics 365 Business Central
online at least once before submitting for validation. We use Docker, and this ensures that you will be testing on
the same as what we validate your app on.
If you test in an on-premises deployment, you might miss errors that would be seen online.
Make sure that you use the correct artifacts for Docker to set up the correct Dynamics 365 Business Central
version number. Use the function Get-BCArtifactUrl in the BcContainerHelper module to retrieve the artifactUrl
of the current version. If you test on a build that is older or much newer than the current version, your app will
most likely fail validation.
Also make sure that you refresh the Docker instance each time you want to submit. If you haven't run your
Docker script to refresh for months, then you are on a much older build.

Use the correct data when you test your app


When we validate apps, we use the base CRONUS demo data. This of course is there for some countries and you
don't have to do anything additional to receive that demo data. However, for countries that are empty and don't
include demo data, you must import the CRONUS evaluation demo data. Not the International CRONUS data,
the evaluation demo data. We do not use custom data and we do not use any other data. We always use the
base evaluation demo data. To get this same data (if you don't have it by default), you follow these instructions:
1. Search for Configuration Packages , and then choose the link.
2. Choose Process > Impor t Predefined Package .
3. Click the link for GB.ENU.EVALUATION .
That will start processing. You will see the process bar.
4. If there are popups at all, just choose Yes or OK .
5. Once the process is complete, choose the Apply Package button, and then choose Yes .
6. Again, if any popups or anything just click through them.
7. Once it completes, sign out of Business Central and then sign back in again.
8. You now have data.

Use the right user for your testing


Do not do your testing with a user that has SUPER permissions marked. The SUPER user can do all without issue
and you won't catch your true app bugs. No live customer will have several users marked with this permission
set. Therefore, we cannot test with it. You need to setup a user in your test environment that only has the BUS
FULL ACCESS permission set, LOCAL, and any of your own permission sets. For information on how to set up
this user, see this blog Enabling Premium Experience in Business Central Sandbox Containers.

Testing your app


Now it is time to test your app. The following are all things you must do as part of your testing effort.
Test your app in its entirety. We expect you to test 100% of the functionality of your app. Testing just a few
areas of your app will not suffice. Test everything.
We are not going to test 100% of the functionality of your app. We expect you to be doing that.
If the testing works for you, it will most likely work for us.
Ensure that no permission errors are thrown for any of your app's functionality.
With the ESSENTIAL user (before you assign your permission sets to it), make sure that the user can still use
the core Business Central without facing permission errors. You must allow that user to do things such as
accessing the Customer card, posting sales order, and so on.

Maintaining your app


Although we do regular testing of your app when we prepare a new version of Dynamics 365 Business Central,
we expect you to do the same on your end. You have access to the same builds that we do through the
Collaborate program. You can do more thorough testing than we can because you know your app the best. By
doing this testing, you can catch future Dynamics 365 Business Central changes that may impact or break your
app. Catching these changes in advance leaves less risk for customers to run into them.
You should be doing regular testing against our next minor (monthly) and next major (bi-annual) release
branches that ports into our monthly service updates. To test against these builds, sign into aka.ms/collaborate,
navigate to packages, and locate the package named Working With Business Central Insider Builds . The
package contains a Shared Access Signature token with which you can download artifacts of future releases for
use with Docker.

See Also
Checklist for Submitting Your App
Rules and Guidelines for AL Code
User Scenario Documentation
2/6/2023 • 3 minutes to read • Edit Online

One of the keys to a successful extension validation is a document that guides the tester through the setup and
usage of the extension. You must include a document that helps Microsoft test some of the key scenarios of your
extension. We want to ensure that we are validating the functionality in the correct manner. Following are some
key points to keep in mind when writing the user scenario document.
Be as detailed as possible. No detail is too small. If a field needs a specific value, include that value in your
document.
Keep the inexperienced user in mind. You know your app well, but other users do not.
Use screenshots as much as possible. They provide a good picture of what you want the user to
accomplish.
Provide all prerequisite and setup steps required for successful test scenario completion.
If your app requires setup of its own, include those details.
If any setup is extensive, consider using the import of Rapid Start packages.
If your app has a dependency on non-standard settings in the core default version of Business Central,
include those details. The Microsoft-provided demo data might not have everything that your app
needs to work properly.
Include the most important functionality scenarios of your extension. We are not looking to test your
entire extension, but we do want to ensure we are validating the most used aspects of your app.
Do not give a summary as to what these scenarios do. List step by step details instead. Again, the
tester doing the validation might not have the same product knowledge as you do.
It should be possible for the inexperienced tester to complete the user scenario test in less than
20 minutes (after installation and startup).

NOTE
This is not the same as the requirement to include Help for your functionality. For more information about getting started
with extending and customizing the Business Central user assistance, see User assistance model.

Use the correct Business Central version


We recommend that you use Docker as a guide for writing your user scenario document. This way, you can take
screenshots and other visuals that really help the tester walk through your validation. Keep these things in mind:
Do not base your user document on an on-premises environment. Business Central on-premises
deployments can have different windows, data, and so on. As a result, your document can lead to confusion
and differences in our results.
Use the correct Business Central version. If you are basing your document on a build that is months old,
many things could now be different in the latest production environment. This also can lead to much
confusion. For more information, see Current Build - Developing for Dynamics 365 Business Central on the
Collaborate site.
Use the correct data for your document. Do not submit a document based on custom data that our testers
will not have access to. You should always base your documents on the base demo CRONUS data and then
include Rapid Start packages with any additional data.
If your app's functionality is different per country, provide that important information. Some of the steps
might be different (for your app) between US and DK. If that is the case, mention that in the document.
Example
Here is an example of the level of detail we are looking for, based on running the Assisted Setup wizard:
1. On the Home Page, click the Setup & Extensions dropdown
2. Choose Assisted Setup
3. Choose the Set up repor ting data link
4. This will launch the wizard for this process

5. Choose Next
6. Choose Next
7. New Name = TestReport1
8. Data Source Type = Page
9. Data Source Id = 22
10. Data Source Name = Customer List
11. Choose Next

12. Choose Publish

See Also
Checklist for Submitting Your App
Rules and Guidelines for AL Code
User assistance model
Restrictions on UI for Objects Exposed as Web
Services
2/6/2023 • 2 minutes to read • Edit Online

Pages and code units that are designed to be exposed as Web services must not generate any UI that would
cause an exception in the calling code.
SUMMARY AND INTENT : When writing code for Web services, you must not use end-user confirmation
dialog boxes, message boxes, or any other page constructs in the code. Because a Web service runs
independently of a user interface, running this type of code causes the code to throw an exception. The
exception can be caught and handled, but the Web service will not complete.
RESO

You might also like