Best practice guides / Dynamics 365

Dynamics 365 Development Best Practice Guide

This guide provides the best practices you need to optimize the following Dynamics 365 (D365) functions: Solutions, Fields, Relationships, Forms, Views, Model-driven Apps, Processes, Web Resources, and Plug-ins.

Last updated: March 27, 2024

Solutions

1. Add a publisher prefix

Adding a prefix to solution components that's relative to you or your organization enables users to quickly identify who created or customized each component.

2. Manage customizations in custom solutions (not default solutions)

Customizations created within default solutions cannot be exported or distributed to other environments, and they use the default publisher, leaving components with an unspecified publisher. Create custom components inside custom solutions, and if you need to customize out-of-the-box components, add them to the custom solution before customizing.

3. Add detailed component descriptions

Adding detailed descriptions to entities, forms, views, fields, and processes prevents confusion and enables fellow developers to easily identify what each component is for.

4. Export unmanaged and managed solutions for every release

Unmanaged solutions can be used to reconfigure the system or set up a new instance if the development environment fails. Managed solutions are used to deploy customizations in higher environments (QA, pre-production, production).

5. Create separate, unmanaged solutions for ribbon customizations

Ribbon Workbench imports entire solutions, recreates each entity ribbon, and then publishes them. Fewer entities reduce ribbon update time.

Fields

1. Use unique field names

Duplicate field names may cause errors while importing data, or confuse users creating personal views, Power Automate flows, and more.

2. Choose the correct field data type

Choose a data type that accurately reflects the data you want to store and supports null values if needed. For example, if time is not required for a date, choose Date Only; if a field allows only two values without any default, choose Option Set.

3. Create alternate keys for fields or groups of fields

Alternate keys prevent users from creating records with duplicate field values or combinations of values. Warning: once a key is deployed to a managed environment, it cannot be deleted.

4. Check 'Disable most recently used items' for filtered lookup fields

This prevents users from selecting unrelated options from recent searches. For example, if lookups are 'State' and 'City', disable most recently used items on 'City' — otherwise users may select a city from recent searches that is irrelevant to the selected state.

Relationships

1. Enable field mapping

Enable field mapping to auto-populate field data from a parent record when a child record is created (common for sub-grids).

Forms

1. Remove asynchronous function calls when saving quick create forms

On quick create forms, the Save & Close button does not wait for asynchronous function calls to complete (e.g., a Retrieve Record WebAPI call). If possible, remove asynchronous calls when saving quick create forms and instead execute them on form load or upon change of field values.

2. Register event handlers for field events programmatically

Use the JavaScript addOnChange method to bind field onChange events instead of binding them from form properties. This gives you programmatic control over field events.

Views

1. Use only alphanumeric characters for view names

Special characters in view names may cause issues when importing from Excel.

2. Limit view columns to show only required fields

Optional fields may not have data and may increase the size of the grid to accommodate empty cells.

3. For sub-grid views, don't add the parent column to the view

If you add a parent column to a sub-grid view, the same value appears for all related records. Example: don't add a Country column on a State sub-grid view inside a Country entity.

4. Add icons for categorical fields

Adding icons for status, gender, rank, profit/loss, etc. enables users to quickly identify field values at a glance.

5. Ensure columns and relative orders are consistent across active and inactive views

This keeps information consistent across both record states.

Model-driven Apps

1. Replace the app's GUID with a user-friendly URL name

Use the app's URL suffix to access the app instead of the globally unique identifier (GUID). The URL suffix is more user-friendly.

Processes

1. Update the stage of Business Process Flow (BPF) with custom fields

Instead of executing moveNext() and movePrevious() from scripts, update custom fields (such as status) directly from scripts. This activates predefined background workflows, plug-ins, and Power Automate flows linked to the BPF entity to update the active stage.

Web Resources

1. Use namespace for JavaScript web resources

Namespaces ensure JavaScript methods are unique and prevent collisions between identifiers.

2. Use relative paths to reference web resources

Relative paths keep web resource references environment-independent, since absolute paths include the environment name.

3. Write code in a common JavaScript web resource and add it to entity forms

This saves time by letting developers quickly reference and reuse common code.

4. Pass ExecutionContext only when necessary; otherwise use FormContext

ExecutionContext is the parent object of FormContext, enabling not just form event handlers but also grid event handlers via GridContext.

5. Bind preSearch on form load and use a global variable for dynamic filtration

Bind the preSearch lookup field event only on form load and update a global variable whenever custom filtration changes. This ensures high performance and easy maintenance of lookup filtration code.

6. Use Xrm.Constants

Use Xrm.Constants to access constants like attribute required levels (none, required, recommended), attribute types (Boolean, date/time, lookup), and form notification levels (error, warning).

7. Open forms with navigation popup

Use Xrm.Navigation.navigateTo to open forms (entity record, entity list, or HTML web resource) as a modal dialog rather than Xrm.Internal.openDialog or jQuery custom dialog frameworks, which are deprecated or unsupported.

8. Use browser-specific web developer tools to debug

Debugging a JavaScript web resource in the console often requires rewriting code. Browser DevTools (Chrome's Run Snippet, Firefox's Scratchpad) run in the page's JavaScript context and are faster than external tools.

Plug-ins

1. Use context.depth when updating fields using plug-ins

If context.depth is not used, it causes infinite recursive plug-in calls.

2. Update an entity by creating a new instance with required fields only

Instead of service.Update(case) directly on the loaded entity, create `Entity temp = new Entity('case')`, set only the fields you need, and call service.Update(temp). This avoids unnecessary field updates.

3. Declare main execution function as static

Declare all other helper functions as private. This reduces code duplication and improves performance.

4. Create separate C# files for constants, XML expressions, and exception handling

Separating these concerns improves code readability and maintenance.

5. Limit plug-in files to a maximum of 8MB

Microsoft Dynamics CRM plug-ins have a maximum size. Exceeding the limit prevents remaining plug-ins from being imported.

References

Need a Dynamics 365 customization audit or development uplift? MAQ Software's Dynamics team can help.

Talk to our team
Dynamics 365 Deployment Best Practices

Dynamics 365 Deployment Best Practices

Deploy Dynamics 365 faster with minimal downtime using our 8 best practices.

Read More