Chapter 25. Plug-ins

A plug-in is a .NET assembly that can be used to intercept events generated from the CRM system to perform a variety of actions. An example of event interception is an entity that will be created, updated, or deleted; and an action can be almost anything. Some common plug-in uses include the following:

Image Performing a complicated update routine on CRM entities/attributes when it might be impractical to use JavaScript or business rules

Image Grabbing data from another system and updating CRM when an entity instance is being created or updated

Image Updating another system programmatically from CRM (such as an accounting system)

Plug-ins

By using plug-ins, you can fire a custom action or event on any entity (for example, on the Account entity either before or after it is created, updated, or deleted). In addition, other events can be handled from a plug-in, such as Assign, Merge, and Handle. Refer to the Dynamics CRM software development kit (SDK) for a complete list of supported events. You can download the SDK from the Microsoft website; search for “Dynamics CRM SDK.”


Note

Not every event works in offline mode of the Microsoft CRM Outlook client. Whereas online mode supports all events, offline clients can manage only half of them. Refer to the CRM 2016 SDK for a complete list of events supported in offline mode, in the file called message-entity support for plug-ins.xlsx, which you can find in the SDK.


Figure 25.1 shows the event execution pipeline order in which the event and the plug-in calls are executed.

Image

FIGURE 25.1 Event execution pipeline.


Tip

You don’t need to restart Internet Information Services (IIS) or any other CRM service when you register or unregister plug-ins.


Isolation

Microsoft Dynamics CRM provides for registering plug-ins either in the sandbox (partial trust) or outside the sandbox (full trust). For Microsoft Dynamics CRM Online, plug-ins must be registered in the sandbox; On-Premises and Internet-Facing Deployment options can be registered in the sandbox or out of sandbox (or using the option none, which is out of the sandbox). CRM hosting providers might not support plug-ins without isolation mode for security reasons. Before you attempt to install a plug-in, check with your hosting provider to determine whether it allows you to use non-sandbox plug-ins. If a plug-in is registered in the sandbox in isolation mode, it will run in partial trust and won’t be allowed to access some resources on the server, such as files, the Registry, databases, and so on. This level of isolation, however, allows access to HTTP and HTTPS web resources for external web services communication. The sandbox allows a plug-in to access the CRM services to create, update, or delete any entity on the system.

Developing plug-ins in sandbox mode is the recommended action, because it makes them more secure and supported on all the CRM 2016 deployment types (Online and On-Premises). They are also monitored by the CRM system-generated runtime statistics that can be queried using the PluginTypeStatistic entity records. If the sandbox worker process exceeds threshold CPU and memory limits and becomes unresponsive, the system kills it. In this case, currently executing plug-ins fail, but upon the next engagement, the plug-ins execute normally.

Finally, to deploy a plug-in without isolation mode, you need to add it as a deployment administrator, via the CRM Deployment Manager. Failure to do so results in failure to deploy the plug-in.


Tip

Being a deployment administrator is not required for deployment of sandbox plug-ins.


Modes

You can set up plug-ins in synchronous or asynchronous mode. Synchronous mode starts the execution of the plug-in when the event is fired and blocks the CRM application process until the executed method finishes. This option is not recommended if you are performing a process that might take a long time to execute. Regardless of the method used, synchronous or asynchronous, a timeout limit of 2 minutes applies for plug-in executions. If a process needs more time, you should consider using a workflow or another custom background process.


Tip

If you want to prevent another record from being created or updated, synchronous should be the desired mode, in conjunction with the pre-stage (see the next section, “Stages”).


Asynchronous mode releases the application process, and the user can continue working while the code is executed. You can check the execution status of asynchronous plug-ins from Settings > System Jobs. These plug-ins are executed by the Microsoft Dynamics CRM Asynchronous Processing Service, which is a Windows service.


Tip

The Microsoft Dynamics CRM Asynchronous Processing Service includes the following services:

Image Microsoft Dynamics CRM Asynchronous Processing Service (maintenance)

Image Microsoft Dynamics CRM Sandbox Processing Services


Stages

You can set up plug-in steps in the pre-stages (either pre-validation or pre-operation) or post-stages (post-operation):

Image Pre-Stage—This stage is divided into pre-validation and pre-operation and sends control to the plug-in before the real event is executed in the core system. For example, you might attach a plug-in to the Create event of the Account entity; your code would execute before the Account was actually created in the CRM system. With this method, you could prevent the account or the entity record from being created.

Image Post-Stage—This stage is executed after the real event has executed in the core system. So, following the example just described, your code would be executed only after the account record has been created.

Dynamics CRM 2016 allows these stages to participate in SQL transactions as well.

The concept of using transactions now allows the rollback of a plug-in operation. If you have two different plug-ins attached to the same message of an entity and the second plug-in fails, it can now roll back the successful operation performed by the first plug-in. This was not easily done with earlier versions of Dynamics CRM. You can check whether a plug-in is running in a transaction by checking the IsInTransaction property of IPluginExecutionContext. The stages 20 (pre-operation) and 40 (post-operation) are the ones that guarantee to be part of a transaction, whereas stage 10 (pre-validation) might not be part of it.

Deployment Types

There are three deployment types for plug-ins:

Image Server—The plug-in executes on the server. Execution occurs when users use the web client or the Outlook Online client as well as when any workflow is executed.

Image Offline—The plug-in executes on the client user machine where Outlook is running. This is especially useful when you’re running the Outlook client in offline mode.

Image Both—The plug-in executes on the server and in the Outlook client in offline mode. Keep in mind that the plug-in is executed twice: once when Outlook is offline and again when it connects to the server.


Tip

To prevent a plug-in from executing twice because of synchronization, check the IsOfflinePlayback property of IPluginExecutionContext.


The deployment type you select depends on what you want to do. If you need to grab data from an external system and need to have the user connected to the Internet or the network, you should have the plug-in run only on the server side, and the Outlook client will not have network access in offline mode.

When to Use a Plug-in

You should use a plug-in when you need to integrate Microsoft Dynamics CRM with a legacy system or when you want to extend or customize the original functionality or behaviors of Microsoft Dynamics CRM.

Plug-ins are the best choice for enforcing complex business rules of your business. You could use JavaScript events to add validation on the rules you want to enforce; however, those types of validations work only when CRM is used through the native interfaces (such as the web or Outlook client). If you remember that other applications can be interacting with the CRM system through the web services, service endpoints, and so on, the validations and rules enforcement will work always if you put them on plug-ins or business rules. Plug-ins run on the server side, whereas JavaScript validations run on the client side. It is a good practice to put the validation logic in one place on the server side; that way, you know the hardware and resources you can use. Clients have a lot of different setting configurations on their browsers, and in some cases they might cause your validations to not work properly.

Image For more information about business rules, refer to CHAPTER 22Customizing the System.”


Tip

Putting the business rules and validations on plug-ins doesn’t mean you do not need to add validations with JavaScript events. In most cases, it is good to have the validations in both places to avoid unnecessary server calls.



Note

CRM 2016 has come up with real-time (synchronous) workflows that enable power users to control through workflows business logic that used to be controlled through plug-ins. If you are planning to upgrade from CRM 2013/2015 to CRM 2016, you might want to move your business logic from plug-ins to real-time workflows.


Plug-in Development

To develop a plug-in, you must download the Microsoft Dynamics CRM 2016 SDK from the Microsoft website. You can find it at the Microsoft website by searching for “Dynamics CRM SDK.”

Download the MicrosoftDynamicsCRM2016SDK.exe file, save it, and execute it (it is a self-Eetracting cabinet file) by double-clicking the file and entering the directory where you want to extract the files (see Figure 25.2).

Image

FIGURE 25.2 Extracting the SDK files.

To create a plug-in, you must create a new class library project in Visual Studio, using .NET 4.5.2, by selecting File > New > Project. Then select Visual C# > Windows on the left and select Class Library in the middle. Enter a name for the project and select a location and a solution name if they don’t auto-populate when you enter the project name (see Figure 25.3).

Image

FIGURE 25.3 Creating a new class library project for a plug-in.


Note

This version of Microsoft Dynamics CRM 2016 is based on the .NET Framework 4.5.2, and you can use Visual Studio 2013/2015 to create class libraries. Although you can also create class library projects in a variety of languages, including Visual Basic .NET, the examples in this book use C#.


The project template creates a new public class by default. After you create the project, you must add to your project a reference to the Microsoft.Xrm.Sdk.dll file and a reference to Microsoft.Crm.Sdk.Proxy.dll. These dynamic link library (DLL) files are located inside the SDKin subfolder.

Adding References


Tip

You can use NuGet to add the assemblies using the following command:

Install-Package Microsoft.CrmSdk.CoreAssemblies

For more information about NuGet, visit www.nuget.org/packages/Microsoft.CrmSdk.CoreAssemblies/.


To add these references, follow these steps:

1. Go to the Solution Explorer and right-click myPlugin > References (under the root Solution node of the tree). Select Add Reference, as shown in Figure 25.4.

Image

FIGURE 25.4 Adding a reference to a project.

2. Click Browse.

3. Locate the SDKBin folder on your local drive and select both the Microsoft.Xrm.Sdk.dll and Microsoft.Crm.Sdk.Proxy.dll files (see Figure 25.5). (To select more than one file, hold down the Ctrl key while you click the files you want.)

Image

FIGURE 25.5 Selecting the DLLs to reference.

4. Click Add and then click OK to add the references to your project. You can then see these files inside the References folder of your project in the Solution Explorer (see Figure 25.6).

Image

FIGURE 25.6 Checking that the new references were added.

5. Add the using sentence to the Microsoft.Xrm.Sdk namespace and implement the IPlugin interface, as shown in the following code (where you need to rename Class1 with the name of your plug-in):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;

namespace myPlugIn
{
    public class Class1 : IPlugin
    {

  }
}


Tip

You can implement more than one plug-in on the same assembly by using different classes, if you want to.


As with any other interface, you must explicitly implement methods. In the case of the IPlugin interface, you must implement the Execute method, as shown in the following code:

namespace myPlugIn
{
    public class Class1 : IPlugin
    {
     public void Execute(IServiceProvider serviceProvider)
     {
          throw new NotImplementedException();
     }
    }
}


Caution

Using early binding in plug-ins is not recommended as early binding produces a bigger assembly and can bring more challenges than late binding. To learn more about these options, refer to Chapter 23, “Web Services.”


The following sections explain the main classes.

IServiceProvider

The Execute method of the IPlugin interface has only one parameter, named serviceProvider, which is IServiceProvider type. From this parameter, you can get the plug-in execution context by entering the following code:

IPluginExecutionContext context =
(IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

This main parameter has a method, GetService, that enables you to get other services from the service provider, such as the context of the organization and the context of the tracer service. This enables you to interact with the current CRM trace to add debugging information for the execution of your plug-in. to get an instance of the trace service, use the following code:

ITracingService tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));

IPluginExecutionContext inherits from IExecutionContext, which is a more generic interface that is also implemented by other classes, such as the RemoteExecutionContext class used for Windows Azure integrations.

IExecutionContext

From the IExecutionContext object, you can query all the property values associated with the entity and event context where the method is being executed. This class contains the properties described in the following sections.

BusinessUnitId

The BusinessUnitId property returns the GUID (global unique identifier) of the business unit of the user making the request. Notice that this is not the GUID of the entity’s record. To return the GUID of the entity’s record, you use the new property PrimaryEntityId.

CorrelationId

The CorrelationId property returns the GUID of the plug-in event instance. Every time the event fires, it generates a new GUID that can be read from this property.

You can use this property for tracking and logging purposes, especially when you have more than one plug-in attached to the same event, to see whether the codes execute for the same event pipeline.

Depth

The Depth property returns the depth of the originated event. This property is of integer type and grows as the plug-in execution goes deeper, which can happen if your plug-in calls a web service to update another entity that also fires an event for another plug-in’s execution code. You might need to check the value of this property to prevent infinite loops if the web service calls a method that fires the same plug-in execution that might produce a deadlock. The maximum number for the Depth property is set to 8. A system administrator can increase this value by running the PowerShell command Set-CrmSetting on the CRM server by changing the value of the WorkflowSettings.MaxDepth setting.

InitiatingUserId

The InitiatingUserId property returns the GUID of the user who initially invoked the operation.

InputParameters

The InputParameters property is a collection of the request parameters associated with the event. You can use this property to retrieve the entity object for which the event is fired:

Entity entity = (Entity)context.InputParameters["Target"];


Tip

You may receive the following error when building a solution:

'System.Runtime.Serialization.IExtensibleDataObject' is defined in an assembly
that is not referenced.

To fix this, add a reference to the assembly System.Runtime.Serialization.


The type of the target input parameter depends on the message. For example, the delete message returns an EntityReference:

EntityReference entity = (EntityReference)context.InputParameters["Target"];

It is a good practice to verify the type of the target parameter, as follows:

if (context.InputParameters.Contains("Target") && context.InputParameters["Target"]
is Entity)
{
    Entity entity = (Entity)context.InputParameters["Target"];
}

Also, you must make sure the entity contains the attribute you are looking for. The entity returned in the target parameter will contain only the attributes that were modified or created, and not all the entity fields. For example, the following code attempts to change the name of the Account entity:

if (entity.Attributes.Contains("name"))
{
entity.Attributes["name"] = "updated name";
}
else
{
    entity.Attributes.Add("name", " new account name");
}

For example, if there is an update operation in the account record where the name was not changed, that field won’t be included in the target parameter. If for some reason you always need to know the value of this field, you can register an image for your plug-in. See the “Images” section, later in this chapter.

IsExecutingOffline

The IsExecutingOffline property is used only for Outlook clients and returns whether the Outlook client is running in online or offline mode. This property is a Boolean type where true = offline mode.

IsInTransaction

The IsInTransaction property is used to determine whether the operation is participating in a SQL transaction. This property is a Boolean type where true = is in transaction.

IsOfflinePlayback

The IsOfflinePlayback property is used only for Outlook clients and returns whether the Outlook client is transitioning from offline to online mode. This property is a Boolean type where true = synchronizing with the server.

IsolationMode

The IsolationMode property returns the IsolationMode mode in which the plug-in is running (none or sandbox). This parameter is an integer type where 0 = none and 2 = sandbox.

MessageName

The MessageName property returns the name of the event that invoked the plug-in. It is a string. These are the supported messages for custom entities:

Assign
Create
Delete
GrantAccess
ModifyAccess
Retrieve
RetrieveMultiple
RetrieveSharesPrincipalsAndAccess
RevokeAccess
SetStateDynamicEntity
Update

System entities can support other system messages. Refer to the message-entity support for plug-ins.xlsx file in the CRM SDK for a complete list of System entity–supported messages.

Mode

The Mode property returns the mode in which the plug-in is running. It can be synchronous or asynchronous. This parameter is an integer type where

0 = synchronous and 1 = asynchronous.

OperationCreatedOn

The OperationCreatedOn property returns the datetime value of the SystemJob created for execution of an asynchronous plug-in. This value is null in the case of a synchronous plug-in.

OperationId

The OperationId property returns the operation GUID when the plug-in is running in asynchronous mode and gives you the ID of the current system job. In synchronous mode, this value is always an empty GUID.

OrganizationId

The OrganizationId property returns the organization GUID where the plug-in is running. Even though plug-ins are registered by organization ID, having this property helps if you have a generic plug-in that will be installed in different organizations and you need to perform different tasks, depending on the organization the plug-in is running. This way, you maintain only one Visual Studio solution and set of source code.

OrganizationName

The OrganizationName property returns the name of the organization where the plug-in is running. With this attribute, you do not need to make an API call to get the organization name by giving the organization ID.

OutputParameters

OutputParameters is the collection of properties returned by an event. A common output parameter is the GUID returned when an entity is created. Be careful when adding parameters on pre-stages because they could be overwritten after the system processes the core event. For example, suppose that you want to return the accountid property that is created when a plug-in is attached to the Create event of the Account entity in the post-stage:

Guid myAccountID = (Guid)context.OutputParameters["id"];

OwningExtension

The OwningExtension property returns the data associated with the SdkMessage ProcessingStep or the service endpoint. This property type is an EntityReference class from which you can get, for example, the description of the step that is running where you registered the plug-in.

ParentContext

The ParentContext property returns the context of the parent pipeline operation, which may happen if the plug-in is registered in the pre- or post-operations. Sometime the plug-in requires another internal messages to be executed, and this property gives you the context of the parent execution.

PostEntityImages

The PostEntityImages property contains the collection of the images with the properties’ names and values after the system executes the core operation.


Note

With PostEntityImages, you need to specify the images and what properties you want to have in this collection when you register the plug-in.


PreEntityImages

The PreEntityImages property contains the collection of the images with the properties and values before the system executes the core operation. This is very useful on post-stages to see what values the associated entity had before an update operation, for example.


Note

As with PostEntityImages, you need to specify the images and what properties you want to have with this collection when you register the plug-in.


PrimaryEntityId

The PrimaryEntityId property returns the GUID of the entity’s record where the operation is performed. If you are working with accounts or contacts, you should use the following code to get the entity record identifier:

Guid id = context.PrimaryEntityId;

PrimaryEntityName

The PrimaryEntityName property gets the related primary entity name you specified when you registered the plug-in. This property is a type of string and returns the name of the associated entity—for example, Account, Contact, and so on.

RequestId

The RequestId property gets the ID (GUID) of the event execution pipeline. It returns null for synchronous operations.

SecondaryEntityName

The SecondaryEntityName property gets the related secondary entity name if you specified one when registering the plug-in. This entity is commonly used in the Parent Account or Contact of the Account entity. This property is a type of string and returns the string None if no secondary entity name is specified.

SharedVariables

The SharedVariables property is used as a common repository to store properties that plug-ins will share. It is useful when you need to pass a parameter value from one plug-in to another that is being executed in the same event pipeline.

Stage

The Stage property gets the stage at which the synchronous plug-in execution is registered. It can have any of the following values:

Image 10 = pre-validation

Image 20 = pre-operation

Image 40 = post-operation

UserId

The UserId property returns the GUID of the user who is executing the operation. Notice that if you impersonate the plug-in’s SDK message-processing step, as explained later in this chapter, this returns the user you configure there and not the user who originally initiated the operation, which you find in the InitiatedUserId attribute.

IOrganizationServiceFactory

If you need to create an instance of the organization service, you can do it by using the IOrganizationServiceFactory instance.

The service instance returned by IOrganizationServiceFactory has the method CreateOrganizationService, which is used get an instance of IOrganizationService.

Here is an example of how to use IOrganizationService and the CreateOrganizationService method:

namespace myPlugIn
{
    public class Class1 : IPlugin
    {
       public void Execute(IServiceProvider serviceProvider)
       {

          IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));

          IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)
serviceProvider.GetService(typeof(IOrganizationServiceFactory));

          IOrganizationService service = serviceFactory.CreateOrganizationService
(context.UserId);
        }
    }
}

IOrganizationService

To use the CRM services, you need to get an instance of IOrganizationService, which provides programmatic access to metadata and data for an organization.

The service instance returned by IOrganizationService has the following methods:

Image Associate—Used to create a link between records.

Image Create—Used to create records.

Image Delete—Used to delete records.

Image Disassociate—Used to remove a link between records.

Image Execute—Used, for example, to execute Fetch queries.

Image Retrieve—Used to retrieve a record.

Image RetrieveMultiple—Used to retrieve more than one record.

Image Update—Used to update records.

Image For more information about how to use this service and its methods, refer to CHAPTER 23.

ITracingService

For debugging purposes, you can use tracing by getting an instance of ITracingService. The service instance returned by IOrganizationService has the method Trace, which is used to add login information that you can then read when profiling a plug-in.

Here is an example of how to use ITracingService and the Trace method:

namespace myPlugIn
{
    public class Class1 : IPlugin
    {
       public void Execute(IServiceProvider serviceProvider)
       {
          ITracingService myTracingService =
            (ITracingService)serviceProvider.GetService(typeof(ITracingService));
          try
          {
              // do your work
             myTracingService.Trace("Plug-in execution starts");
         }
         catch (Exception ex)
         {
             myTracingService.Trace("Plug-in Exception: {0}", ex.ToString());
             throw;
         }
       }
    }
}

Plug-in Deployment

Before delving into the details about plug-in development, you should take a look at the deployment options so that you can easily follow the sample code included later in this chapter.

The first step in plug-in deployment involves registering your plug-in and signing the assembly with a strong name key file. A strong name key is necessary for security so that the assembly can be trusted to execute external code, such as when invoking a web service. To sign your assemblies, follow these steps:

1. In the Solution Explorer, right-click your project and select Properties (see Figure 25.7).

Image

FIGURE 25.7 Properties menu item of the project.

2. Go to the Signing tab and check the Sign the Assembly check box (see Figure 25.8).

Image

FIGURE 25.8 Signing tab.

3. Create a new strong name key file by selecting New from the drop-down, as shown in Figure 25.9.

Image

FIGURE 25.9 Selecting a new strong name key file.

4. Enter a name for the key file and, optionally (but recommended), enter a password to protect the strong name key (see Figure 25.10).

Image

FIGURE 25.10 Creating a strong name key.


Tip

Be sure to give the password to any developer who will need to build this plug-in.


5. Click OK to close the dialog, and you see the newly created strong name key added to your project in the Solution Explorer (see Figure 25.11).

Image

FIGURE 25.11 Solution Explorer with the newly created strong name key.

To deploy your plug-in, you need to register it. You can do this programmatically or using a tool that comes with the CRM SDK called the Plug-in Registration Tool. The Plug-in Registration Tool comes as an application and is located in the SDKToolsPluginRegistration folder.


Note

You can also use the Plug-in Registration Tool to register Service Bus endpoints. These types of components are explained in detail in Chapter 24, “Azure Extensions.” The Plug-in Registration Tool is also used to register custom workflow activities, which are fully covered in Chapter 26, “Process Development.”


Integrating the Plug-in Registration Tool with Visual Studio 2015

You can follow these steps to integrate the Plug-in Registration Tool into Visual Studio 2015 as a recommended option:

1. In Visual Studio 2015, select Tools > External Tools (see Figure 25.12). The External Tools dialog, shown in Figure 25.13, appears.

Image

FIGURE 25.12 Visual Studio External Tools menu option.

Image

FIGURE 25.13 External Tools dialog.

2. Click the Add button and change the title to CRM Plug-in Registration (see Figure 25.14).

Image

FIGURE 25.14 Adding CRM Plug-in Registration.

3. Click the ellipsis ... button next to the Command field and locate the PluginRegistration.exe application file, which you should find in the SDKToolsPluginRegistration folder (see Figure 25.15).

Image

FIGURE 25.15 Locating the PluginRegistration.exe application.

4. Click Open to close the dialog and click OK to close the External Tools dialog. In addition, change the initial directory to the directory where you have the Plug-in Registration Tool.

You can now run the Plug-in Registration Tool from Visual Studio 2015 by selecting Tools > CRM Plug-in Registration (see Figure 25.16).

Image

FIGURE 25.16 Accessing the Plug-in Registration Tool from Visual Studio.

Registering a Plug-in

When you run the Plug-in Registration Tool, you must first click Create New Connection and select the deployment type, which can be either On-Premises or Office365 (used for CRM Online deployments). Then you need to enter information for the server name and port (typically 80 for HTTP and 443 for HTTP when using SSL) and the authentication source. You also need to check the Display List of Available Organizations check box, as shown in Figure 25.17.

Image

FIGURE 25.17 Registering the plug-in.

The Plug-in Registration Tool has the option to use the credentials of the user you are already logged in as, so you don’t have to enter the username and password every time you run the tool. If you want to use a different user credential, you can uncheck the Use Default Credentials check box (refer to Figure 25.17) and enter a valid username, password, and domain.


Tip

The option to use the credentials of the user you are logged in as works only with On-Premises deployments.


The username and password must be valid Windows account credentials and for a valid Microsoft CRM user with administrative roles assigned, as well as deployment administrator rights that can be added through the CRM Deployment Manager. If the plug-in is going to be registered with the isolation mode set to Sandbox, the user doesn’t need to be a deployment administrator; in that case, the CRM system administrator role is enough.

After you enter these values, click Login to connect to the organization and then select the organization you want to connect with.

If you need to connect to another organization, you need to click Create New Connection again. Doing so does not disconnect you from the first organization you connected to before but does create another tab with the second organization name you selected (see Figure 25.18).

Image

FIGURE 25.18 Connected to more than one organization.

If you are connected successfully to the CRM organization, you see the Registered Plug-ins & Custom Workflow Activities page, as shown in Figure 25.18.

Follow these steps to complete the plug-in registration:

1. Build the Visual Studio solution project so you can register the generated DLL, and make sure to build the assembly signed with a strong key to avoid a build error. Then click the Register button and then click Register New Assembly. The Register New Assembly dialog, shown in Figure 25.19, opens.

Image

FIGURE 25.19 Assembly registration window.

2. Locate your assembly by clicking the ellipsis ... button near the top of the Register New Assembly dialog. Select Sandbox under Step 3. (Remember that the sandbox isolation mode is preferred when deploying to a CRM Online environment.) Select Database under Step 4 and be sure to select the class you want to register that appears on the list. Then click the Register Selected Plugins button. When the assembly is registered, a confirmation window appears, as shown in Figure 25.20.

Image

FIGURE 25.20 Registered assembly confirmation.

3. Expand the assembly you registered to make sure your assembly was properly registered (see Figure 25.21).

Image

FIGURE 25.21 Reviewing assembly registration.

4. Associate the assembly with an entity and an event by clicking the assembly you registered in the previous steps and selecting Register > Register New Step (see Figure 25.22).

Image

FIGURE 25.22 Register New Step menu option.

5. To register a step (and select the entity and event), enter the message Create in the Message field and account in the Primary Entity field (see Figure 25.23).

Image

FIGURE 25.23 The Register New Step dialog box.


Note

The Message and Primary Entity text boxes have IntelliSense, so you are presented with a list of values after you enter the first characters.


6. Select the Pre-Operation option from the Event Pipeline Stage of Execution list and leave the other radio buttons set to their default values, as shown in Figure 25.23.


Tip

You can add impersonation to the plug-in step execution by changing the Run in User’s Context field. By default, this value is set to the calling user, which is the user that is executing the operation (Create, Update, or Delete). However, in some cases, you need to do operations in your plug-in where the calling user might not have permissions. In such a case, you can either specify a different user with a higher role and privileges or use the CRM System user (an internal user), which has all the privileges. If you selected a different user, you can find out know who was the original user who fired the message by checking the value of the InitiatingUserId field of IExecutionContext.


While registering a plug-in, you can store configuration information, using the Secure Configuration and Unsecure Configuration boxes, shown in Figure 25.23. You can store data in any format you want. You can retrieve this information in plug-in code by using a plug-in constructor:

public myPlugin()
public myPlugin(string unsecure)
public myPlugin(string unsecure, string secure)

The first string parameter contains unsecure information, and the second one contains secure information. Secure configuration is not accessible in plug-ins executing in offline mode. Secure configuration is good for passing sensitive data, such as a connection string that contains a username and password.

7. Click Register New Step to close this dialog box, and you see the new step registered (see Figure 25.24).

Image

FIGURE 25.24 Step registration review.

As you saw in Figure 25.19, you can deploy an assembly to either the local hard disk or the database server or to the GAC (Global Assembly Cache). The database is the recommended option for production environments that might be deployed on different servers, such as a load-balanced deployment. This way you don’t need to deploy the assembly on every server. The local hard disk option is the recommended option for debugging purposes.

Be sure to properly debug and test your plug-in before implementing it to a production environment. If a plug-in has an error, users cannot create accounts if you attached the plug-in to the account Create event and the pre-stage (see Figure 25.25).

Image

FIGURE 25.25 Plug-in errors and exceptions prevent users from creating records on pre-stage.

Image SEE the “Plug-in DebuggingSECTION, later in this chapter, for help on debugging.


Tip

With exceptions thrown in plug-ins registered as synchronous, the user gets a dialog about the error. With exceptions thrown in plug-ins registered in asynchronous mode, the exceptions are logged in the system jobs, which you can see by going to the CRM web application and selecting Settings > System Jobs.


Filtering Attributes

When registering a plug-in on the Update method, it is a best practice to filter or specify the fields for which you want the plug-in to be fired. For example, you might want the plug-in to be fired only if the Name field of the Account entity changes. If you don’t configure the filtering attributes, the plug-in will fire if other fields change, unnecessarily decreasing the performance of the CRM server.

Filter or specifying the fields for which you want the plug-in to be fired is something you can do when you create a new step for the Update method (see Figure 25.26).

Image

FIGURE 25.26 Filtering attributes for the Update method.

Images

Images are useful for update operations; they help you determine the original value of a field before a user fired an update operation.

For example, if you want to compare the value of the Account Name field of the Account entity, instead of getting an instance of the IOrganizationServiceFactory to create IOrganizationService and perform a Retrieve method (which junior CRM developers sometimes do), you can just configure this field on a pre-image and read it directly from there without doing any web service call that will decrease the performance of the server.

You need to create images by using the Plug-in Registration Tool. To to so navigate to Register New Image as shown in Figure 25.27.

Image

FIGURE 25.27 Register New Image menu option.

In the Register New Image Dialog that appears, set Image Type to be Pre Image or Post Image, enter a name for the image, enter an entity alias, and, in the Parameters field, select the attributes or fields you want the image to contain (see Figure 25.28). Click the Register Image button, and you see the image inside the plug-in (see Figure 25.29).

Image

FIGURE 25.28 Register New Image dialog.

Image

FIGURE 25.29 Image registered.

Unregister a Plug-in

To unregister a plug-in, you select the plug-in you want to delete, the Assembly node, and then click the Unregister button. The confirmation dialog shown in Figure 25.30 appears.

Image

FIGURE 25.30 Plug-in unregistration confirmation dialog.

Click Yes to confirm the operation, and you see a success dialog, as shown in Figure 25.31.

Image

FIGURE 25.31 Successful plug-in unregistration.


Note

The use of the Plug-in Registration Tool is necessary to register plug-ins only when you are developing them. When you are distributing a plug-in to a production environment (or to another client), you don’t need to use this tool because you can use solutions to deploy your plug-in for distribution t.


Plug-in Debugging

You can debug a plug-in in two ways. The first, as shown in Table 25.1, is by attaching the debugger to the host process. The second is by using Plug-in Profiler. It is recommended that you use either of these methods in a development environment because both methods use Visual Studio and will interrupt all user activity with the server if you attempt to enable debugging in a production environment.

Image

TABLE 25.1 Attaching the Debugger to a Host Process

Before trying either debugging method, you need to build your plug-in with debug mode and put the PDB (project database) file generated by the compiler in the following directory (assuming that you have the CRM server installed on C:Program FilesMicrosoft Dynamics CRM): C:Program FilesMicrosoft Dynamics CRMServerinassembly. This file is located in the output folder of your Visual Studio project, which is typically located at debugin.

Unfortunately, you must restart the IIS after copying the PDB file. You can do this via the command prompt by running the following command:

Iisreset

You can also restart the IIS by using a PowerShell command, like this:

Restart-Service W3SVC, WAS -force


Tip

You must copy the PDB file every time you rebuild the solution in Visual Studio and then restart the IIS.



Caution

You must have Visual Studio installed on the server where the CRM server is installed, or you can also install the Visual Studio 2015 Remote Debugger on the server and debug from a development workstation. The example in this section assumes that you have Visual Studio (2015 or later) installed on the same server where the CRM server is installed.


Attaching the Debugger to the Host Process

When you debug by attaching the debugger to the host process, you have to open your plug-in solution in Visual Studio 2015 first and put breakpoints where you want to stop and debug your code. To set a breakpoint, press F9 (see Figure 25.32).

Image

FIGURE 25.32 Setting breakpoints in your code.

You must attach the Visual Studio debugger to the w3wp.exe process, for example, to debug an online plug-in. To do that, select Debug > Attach to Process, as shown in Figure 25.33.

Image

FIGURE 25.33 Attach to Process menu option.

When the Attach to Process dialog appears, check the Show Processes from All Users check box and select the w3wp.exe process, as shown in Figure 25.34.

Image

FIGURE 25.34 Attaching the debugger to the w3wp.exe process.


Note

If you can’t find the w3wp.exe process, it is probably because you need to first open an Internet Explorer window and browse to your CRM organization URL so that IIS will load the application pool represented by w3wp.exe.

You might also find that there is more than one instance of the w3wp.exe process running; this might depend on the number of different websites and application pools running on the same IIS. Because it is hard to say on which one your application is running, we recommend attaching to all the w3wp.exe instances.


If you are using the remote debugger, you must change the qualifier name to the name of the computer where the CRM and the remote debugger are installed.

If the plug-in has been registered with sandbox isolation mode, you must attach to another process instead of the w3wp.exe process. The process that hosts the plug-ins on a sandbox is called Microsoft.Crm.Sandbox.HostService.exe.

Click the Attach button to start debugging the plug-in.

Assuming that you registered the plug-in and associated it to the Account entity on the Create event (as in the earlier example in this chapter), when you go to the CRM web application and try to create a new account, you are automatically switched to the Visual Studio 2015 application (see Figure 25.35) after you click the Save or Save and Close buttons on the Account form.

Image

FIGURE 25.35 Debugging the plug-in.

Plug-in Profiler

If you need to debug CRM Online plug-ins or plug-ins in a production environment, you should use Plug-in Profiler. You can install Plug-in Profiler from the Plug-in Registration Tool. To do so, follow these steps:

1. Open the Plug-in Registration Tool, connect to your organization, and click the Install Profiler button (see Figure 25.36).

Image

FIGURE 25.36 Installing the Plug-in Profiler.

2. When the Plug-in Profiler is installed successfully, make sure it exists under the assemblies (see Figure 25.37).

Image

FIGURE 25.37 Plug-in Profiler.

3. Select the plug-in step that you want to debug, and you see the Start Profiling button available in addition to the Debug button (see Figure 25.38).

Image

FIGURE 25.38 Start Profiling button.

4. Click the Start Profiling button, and the Profiler Settings dialog appears (see Figure 25.39). These profiling settings are good for most scenarios. Click OK.

Image

FIGURE 25.39 Profiler Settings dialog box.

5. Perform the steps in CRM so that the plug-in step you are profiling gets executed. The Business Process Error dialog box appears (see Figure 25.40).

Image

FIGURE 25.40 Business Process Error dialog box.

6. Click the Download Log File button to save the ErrorDetails.txt file on your computer. This log file contains the profile that the Plug-in Profiler will use to play back execution. Open the plug-in solution in Visual Studio and go to Debug > Attach Process and select PluginRegistration.exe (see Figure 25.41). Set a breakpoint in the plug-in code.

Image

FIGURE 25.41 Attaching the debugger to PluginRegistration.exe.

7. Go back to the Plug-in Registration Tool and click the Reply Plug-in Execution button that is on the command bar or select the step you are profiling and click Debug. Select ErrorDetails.txt for the profile location (Step 1) and select the debug version of the plug-in assembly for the assembly location (Step 2) (see Figure 25.42).

Image

FIGURE 25.42 Debug plug-in.

You can optionally click the down arrow to download the profile execution log from the server (see Figure 25.43). You will have files there if you previously selected Persist to Entity in the profile settings when you started the Plug-in Profiler.

Image

FIGURE 25.43 Selecting a profile from the CRM server.

8. Click Start Execution, and debugging starts in Visual Studio.

Plug-in Samples

The SDK comes with some plug-in samples:

Image AccountNumberPlugin—This sample creates a random account number when an account is created.

Image FollowupPlugin—This sample creates a Task activity when an account is created.

Image PreEventPlugin—This sample demonstrates the use of shared variables to send data through different plug-ins.

Image WebClientPlugin—This sample shows how to access a network resource in a sandboxed plug-in.

Image AdvancedPlugin—This sample shows how to use pre- and post-images, tracing, how to pass secure and unsecure information, and so on.

You can find the code for these samples in C#, within the SDK, in the sdksamplecodecsplug-ins folder.

You can download the SDK from the Microsoft website; search for “Dynamics CRM SDK.”


Tip

Because Microsoft often updates the SDK, it is a good idea to check the download site for updated versions.


Plug-in Distribution

When you develop a plug-in, you register it by using the Plug-in Registration Tool, as explained earlier in this chapter. When you are done with the development and ready to distribute the plug-in, you can do so by creating a solution. Make sure you include the plug-in assembly and the SDK message processing steps in your solution (see Figure 25.44).

Image

FIGURE 25.44 CRM solution.

Image To learn more about working with solutions in Dynamics CRM 2016, refer to CHAPTER 22, “Customizing the System.”

When importing your plug-in solution to another CRM organization, make sure you check the check box Enable Any SDK Message Processing Steps Included in the Solution, or your plug-in won’t work (see Figure 25.45).

Image

FIGURE 25.45 Enabling Any SDK Message Processing Steps Included in the Solution check box when importing solutions.


Caution

Be careful if you change the managed properties of the SDK message processing steps to false. If a user who imports your solution unchecks the Any SDK Message Processing Steps Included in the Solution when importing the solution, the only way to enable the steps is by using the Plug-in Registration Tool because the message steps don’t show up in the installed solution.


Be careful about using secured configurations in the plug-in SDK message processing steps registration. The secure configuration is encrypted with a specific organization key and might be different from one organization to another. You might need to update this secure configuration manually for each environment where you install your plug-in solution.

Summary

In this chapter, you have learned about plug-ins—what they are and when it is recommended to use them. You have created a basic plug-in and reviewed all the development properties of the IServiceProvider, IExecutionContext, and IPluginExecutionContext interfaces. You have learned how to deploy and register plug-ins by using the Plug-in Registration Tool within the UI. You have also learned how to test and debug plug-ins in two ways: by attaching the debugger to the w3wp.exe process and by using the Plug-in Profiler. Finally, you have learned how to distribute your plug-ins to other Dynamics CRM organizations using solutions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset