Skip to content
January 22, 2019 / inventcrm

Best Practices for Dynamics CRM Plugins

I like to share Dynamics CRM plugin best practice.

For improved performance, Microsoft Dynamics 365 caches plug-in instances. The plug-in’s Execute method should be written to be stateless because the constructor is not called for every invocation of the plug-in. Also, multiple system threads could execute the plug-in at the same time.

All per invocation state information is stored in the context, so you should not use global variables or attempt to store any data in member variables for use during the next plug-in invocation unless that data was obtained from the configuration parameter provided to the constructor. Changes to a plug-ins registration will cause the plug-in to be re-initialized.

Its a best practice to check for the target entity name and message name at the beginning of the plugin execute message to avoid running the plugin unintentionally.

Entity Check
Before continuing development of Plugin, ensure that the fired event is for your entity (Check if Target is your entity). For example, if we are expecting Entity to be Account we can check target like this:

Entity entity = (Entity)context.InputParameters[“Target”];
if (entity.LogicalName != “account”)
return;

When you want to update fields on a record, it’s good practice to create a new entity or early bound type of the record and only add the fields you want to update. By only updating the fields you are changing you reduce triggering other plugins running needlessly.

Update Same Entity
Best practices advise us that if you need to update same Entity to use Pre-Update Plugin which will not trigger this Plugin again and potential make loops which can broke execution of Plugin.

Use Early Bound Types
If your Plugin is well defined and you know all the entities that will be included in process it is the best way to use Early Bound Types. One advantage is that code’s compile verification check is done, so you will know all the errors before deployment of Plugin. You can generate Early Type Classes using CrmSvcUtil tool that comes with Dynamics CRM Development SDKs.

When retrieving an entity using SDK, make sure you are instantiating a new object (not just assigning a reference) and assigning it to the returned object from the retrieve SDK message for better performance.

Do not update the retrieve Target entity because it will update all fields included in the target entity. The primary entity targeted by a platform create or update event should not be updated within the context of plug-in execution. Developers should instead design their plug-in to execute in a stage prior to the core operation and manipulate the target object in the Input Parameters.

The common method to avoid a recurring plugin is to check if a plugins depth > 1. This would stop the plugin from being run if was triggered from any other plugin. The plugin would only run if triggered from the CRM form. This can resolve the problem of plugins firing more than once but it stops plugins being triggered from other plugins, this might not be the functionality you require.

Use common Methods
There are several methods that can be used to process different messages that can be trigger for plugins, but best practices recommend to use common methods like Create, Delete or Update instead Execute method. The reason is that Plugin should only be triggered for specific event, not for every general event. It consume less time and it is cost efficient

Never save the Organization service in the CRM execution context in a static variable as this will lead to lots of OpenDataReader errors thrown by the CRM platform since we must keep the plugin/custom step stateless as per MSDN plugin best practices.

You need to have proper exception handling for your developed plugins to better troubleshoot any unexpected behaviors, for synchronous plug-ins, you can optionally display a custom error message in the error dialog of the web application by having your plug-in throw an InvalidPluginExecutionException exception with the custom message string as the exception Message property value, before throw the exception its good practice to log the exception error, origin and any other kind of helpful logging information in your custom logging location.

If you throw InvalidPluginExecutionException and do not provide a custom message, a generic default message is displayed in the error dialog. It is recommended that plug-ins only pass an InvalidPluginExecutionException back to the platform.

Exception Handling
Always use try catch block in your plugin so that execution of your plugin is controlled so that user does not experience unwanted errors which can affect all the other processes.

Plug-ins should exist with others in a project and not be isolated. An example of an exception to this recommendation would be if a plug-in needed to be selectively deployed to an environment, whereas the others are not to be deployed. There are two areas of impact for this observed pattern of a single plug-in per assembly:

Performance – each plug-in assembly has a lifecycle that is managed by the CRM deployment, which includes loading, caching, and unloading. Having more than one assembly containing plug-ins causes more work to be done on the server and could affect the time in which it takes for a plug-in to execute.
Maintainability – having more than one project in Visual Studio can make it more difficult to manage. It also adds additional steps when packaging a solution and managing deployments.

Consider merging isolated plug-ins into a single Visual Studio project and assembly.Kindly use ILMerge of merging into single assembly.

Use NOLOCK hint for Microsoft Dynamics CRM QueryExpression and FetchXml requests for CRM entities that are not having frequent changes like configuration for better query execution performance.

Update plug-in target entity only contains the updated attributes. However, often the plug-in will require information from other attributes as well. Instead of issuing a retrieve query, the best practice is to push the required data in an image instead by using the Pre-Image.

Its advised for logging purposes to use ready made libraries like Nlog (NLogger) as they are optimized libraries for handling concurrency and high workload scenarios with many logging options and providers.

Avoid usage of batch request types like ExecuteMutipleRequest in plug-ins and workflow activities. Use these batch messages where code is being executed outside of the platform execution pipeline, such as integration scenarios where network latency would likely reduce the throughput and increase the duration of larger, bulk operations.

ExecuteMultiple and ExecuteTransaction messages are considered batch request messages. Their purpose is to minimize round trips between client and server over high-latency connections. Plug-ins either execute directly within the application process or in close proximity when sandbox-isolated, meaning latency is rarely an issue. Plug-in code should be very focused operations that execute quickly and minimize blocking to avoid exceeding timeout thresholds and ensure a responsive system for synchronous scenarios.

Debugging in Dynamics CRM Plugin
Tracing is something that is included in Dynamics CRM and it provides good way of debugging Plugin. Other way of debugging code for earlier version of CRM is for async Plugins. In System Jobs you can find a lot of information regarding execution of your Plugin.

References:

https://docs.microsoft.com/en-us/previous-versions/dynamicscrm-2016/developers-guide/gg328263(v=crm.8)

https://docs.microsoft.com/en-us/dynamics365/customer-engagement/guidance/server/avoid-batch-requests-plugin

https://docs.microsoft.com/en-us/previous-versions/dynamicscrm-2016/developers-guide/gg326836(v%3dcrm.8)

Hope this blog post helps you.

Leave a comment