Dynamics 365 Plug-in Step-by-Step
Tags: microsoft365, dynamics, plugin, crm
Published: 2023-07-13 16:18:53

 Microsoft Dynamics 365 is a business agnostic product that provides a flexible and customizable platform for organizations across various industries. Plugins further enhance this agnostic nature by allowing businesses to tailor the platform to their specific requirements and extend its functionality beyond the out-of-the-box features.
 Plugins are server-side custom components that interact with the platform's services and data. Plugins run within the Dynamics 365 server environment and can be triggered by events (also called messages) that occur within the platform. When a plugin is executed, it can utilize the Dynamics 365 platform's services, such as the Organization Service, to perform various operations, including but not limited to basic CRUD actions: retrieving, creating, updating, and deleting records. 

 To develop a plugin for Microsoft Dynamics 365, you can follow these steps:

**1. Set up your development environment:**
Install Visual Studio Community Edition for Dynamics 365 development.

![visual studio community edition](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6kj0ircsbbu0wqwk2m9i.png)

Under Workloads select .NET desktop development:

![select .NET desktop development](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tek7aooehngw67wbw6z5.png)

Go to Individual Components tab, under development activities, select: Window Workflow Foundation

![select window workflow foundation under development activities](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8c02oa9krlj3pauiliax.png)

Then, click install and select C# environment. 

**2. Create a new plugin project:**

The next step is to create a new project and select Class Library (.NET Framework) and click Next:

![select class library .NET framework](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1mltkl3ibib9ejgcl05l.png)

Configure project and solution names and click Create. The solution contains a collection of projects:

![cofigure name of project and solution](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3s4p22mpgyoc6g42tr1a.png)

Use any meaningful name to Rename `class1.cs`:

![rename class1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kerd22rnjhlp49fzk4g8.png)

**3. Add references:**

Go to tools -> NuGet Package Manger -> Manage NuGet Packages for Solutions. Then, browse (type Dynamics 365 in the search box), select, and install the following:
Package1: `Microsoft.CrmSDK.CoreAssemblies`
package2: `Microsoft.CrmSDK.XrmTooling.PluginRegistrationTool`

Go to Solution Explorer -> right click on References -> Add Reference -> Browse -> Go to `solution name folder` (ClassLibrary1 folder in this example) -> packages -> `Microsoft.CrmSDK.CoreAssemblies` -> lib -> net462 -> add `Microsoft.Xrm.Sdk.dll` -> Ok -> include `using Microsoft.Xrm.Sdk`.

Add `System.ServiceModel` from References:
Go to Solution Explorer -> right click on References -> Add Reference -> Assemblies -> Framework -> type `System.ServiceModel` in the search field -> select `System.ServiceModel` -> Ok -> include `using System.ServiceModel`:

![include SDK and System.ServiceModel libraries](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i9qm6tkjotjeltdetinu.png)

**4. Define the plugin class:**

Create a new class that implements the `IPlugin` interface provided by the Dynamics 365 SDK. Then, implement the `Execute` method provided by `IPlugin` interface, which will be called when the plugin is triggered. 
Go to [Microsoft Documentation](https://learn.microsoft.com/en-us/power-apps/developer/data-platform/write-plug-in) and copy the Execute method logic template:


```
public class MyPlugin : IPlugin
{
  public MyPlugin() {} // Constructor, does nothing

  public void Execute(IServiceProvider serviceProvider)
  {
    // Obtain the execution context
    IPluginExecutionContext context = (IPluginExecutionContext)
      serviceProvider.GetService(typeof(IPluginExecutionContext));

    // Obtain the Organization service reference 
    IOrganizationServiceFactory serviceFactory =
      (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
    IOrganizationService orgService = serviceFactory.CreateOrganizationService(context.UserId);

    // Obtain the Tracing service reference
    ITracingService tracingService =
      (ITracingService)serviceProvider.GetService(typeof(ITracingService));

    try
    {
      // TODO Plug-in business logic goes here. You can access data in the context,
      // and make calls to the Organization web service using the Dataverse SDK.
    }
    catch (FaultException<OrganizationServiceFault> ex)
    {
      throw new InvalidPluginExecutionException("The following error occurred in MyPlugin.", ex);
    }
    catch (Exception ex)
    {
        tracingService.Trace("MyPlugin: error: {0}", ex.ToString());
        throw;
    }
}
```
 The execute method accepts a single `IServiceProvider` parameter which has a single method `GetService`. This method provides access to the execution context data (information about the entity and message request that caused the event and invoked the plugin). Also, `GetService` method provides access to Organization Web Service to perform message request to the database (i.e. read, update, create, delete).

**5. Handle plugin execution:**

 Entity is accessible via context that has `InputParameters` collection which `Contains` an object with a `Target` key along with all data passed in the message request. Entity is a generic class that can represents any record (i.e. contact, account, task...). It provides a collection of the corresponding attributes of a given record on which the plugin is registered. These attributes are accessible using the logical names, not the display names.

```
try
       {
         // Plug-in business logic goes here.  

 string firstName = entity.Attributes["firstname"].ToString();
                    }
 string lastName = entity.Attributes["lastname"].ToString();
         // Assign data to attributes

 entity.Attributes.Add("description", "Greetings! " +  firstName + " " + lastName);
                }
```
The next step is to Sign the assembly with an encrypted algorithm because only signed assemblies are allowed by the cloud platform:
Right click on project -> properties -> signing -> check sign the assembly -> select New -> add key file name -> choose whether to add a password or not -> keep default or change algorithm -> Ok -> save -> build solution. 
After this step, the code is compiled and an assembly should be created in a form of `dll` file.

**6. Register and deploy the plugin:**

Use the plugin registration tool downloaded in step 3 to upload the    `dll` to the cloud file:
Right click on project name -> open folder in explorer -> Go one step up in folder directory -> packages -> `Microsoft.CrmSdk.XrmTooling.PluginRegistrationTool` -> tools -> open `PluginRegistration` -> create new connection -> login using Dynamics 365 credentials, select Office 365, and region -> login:

![Plugin registration tool login](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x8e1bgd6urmdnmrxaolj.png)

Go to Register -> Register new assembly -> browse to project -> bin -> debug -> select `filename.dll` -> open -> select the assembly in step 2 -> keep default setting in steps 3 & 4 -> register -> Ok.

The plugin is now uploaded to the list of assemblies. Next, we should configure when the plugin should be executed:
Select plugin and right click -> click register new step:

![Register new step form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5gtihdngfj5tbot9w1h8.png)
Message: Create -> Primary Entity: contact -> Event Pipeline Stage of Execution: PreOperation -> Register new step.

![Plugin Pipeline: what happens on server?](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/61x18sowp5bnijzcsmft.png)
_Image by Paresh Sharma_ [https://www.tech-quantum.com/d365-understanding-plug-in-pipeline/](url)

The plugin will update the attribute collection of primary entity `contact`which is being passed to the main event. When the user creates an account (first name and last name), the data goes through the pipeline to the Pre-Operation stage and in the `serviceProvider` which will provides the contextual data. From that context, we can extract entity information. In this case, the entity represents `contact` form.

**7. Test the plugin:**

Create a new contact in the Sales Hub:

![create test contact](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/emyfhqfam5e7cdz33ajk.png)

Go to details and check Personal Notes:

![Personal Notes Greeting user](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qymzgfwzaioltlck7ot2.png)

Throughout this blog, we discussed the step-by-step process of developing a plugin, including setting up the development environment, defining the plugin logic, registering, deploying and testing the plugin.

References:
https://learn.microsoft.com/en-us/power-apps/developer/data-platform/plug-ins