Classes and interfaces

In this section, each class and interface of the concept will be explained in details.

Kipon.Xrm.BasePlugin

In most cases your plugin will extend Kipon.Xrm.BasePlugin. This class has all the wire to the Dynamics 365 CE pipeline process. You will expose you need by adding methods according to a naming convention, and the parameters will define witch event to listen for.

No fields or properties in the baseplugin

You should never add fields or properties in the base plugin. It is the Dynamics 365 CE platform that is responsible for creating instances on a need base. These instances are used cross request, and are not reinitialized or garbage collected for each invocation. Having fields or properties can therefore create unpredittable behavior.

Methods

You interact with the pipeline by adding public methods, using a naming convention.

public void On[Stage][Event][Async](parameters) { ... }

Where Stage can be:

  • Validate
  • Pre
  • Post

And event can be:

  • Create
  • Update
  • Delete

An finally for Post event you can add the word Async to indicate that this part of the code should run in a seperate async transaction. (only applies to Post event)

Parameters

The parameters must define what to listen for. This can be done by requesting a strongly typed entity, and a naming convention for the parameter. This approach is supported but it is basically an anti pattern. You should define explicit target, preimage, mergedimage or post images interfaces, implemented by the strongly typed entities to stay solid, and allow this tool to registre what to listen for, and keep the payload of images as low as possible. Diig into the Target, Preimage and Postimage interfaces to learn how to create "jummy jummy" interfaces that describes the exact situation we are listening for.

Naming convention when listening for full strongly typed entities as parameter to a plugin
  • target: The target parameter of the event. (then strongly typed entities including all attributes that has been assigned by the client)
  • preimage: The image of the entity before the event
  • postimage: The image of the entity after the event. Can only be used in post stage
  • mergedimage: A combination of target and preimage. Will populate all values included in the target, and on top add parameters missing from the preimage. In prestage, assigning values to the mergedimage will drain down to the target as well.

Beside injecting target and images data, you can inject services into the plugin methods. The following Microsoft std. service can be injected into plugin methods, or into the constructor of any service

  • Microsoft.Xrm.Sdk.IOrganizationService (avoid, use IUnitOfWork, or specific IQueryable or IRepository instead)
  • Microsoft.Xrm.Sdk.IOrganizationServiceFactory(avoid, see above)
  • Microsoft.Xrm.Sdk.ITracingService
  • Microsoft.Xrm.Sdk.IPluginExecutionContext (use carefully, in most cases the entity event "jummy jummy" interface can handle your needs)

Example


namespace Kipon.PluginExample.Plugins.Account.e0
{
    public class AccountPlugin : Kipon.Xrm.BasePlugin
    {
        public void OnPreUpdate(Entities.Account target)
        {
        }
    }
}

Above code shows how to create a plugin that listen to Account Update. The example is an "anti-pattern" because it takes the full Account as target. The consequence is that this code will be triggered on any update to the account. A better solution is to define a target or merged interface that clearly defines what to listen for, but you should grap the basic idea from the code.

And below an example where a service is also injected, we are listening to more than one event, and a jummy jummy interface has been put in place to describe what part of the account we are interested in:


namespace Kipon.PluginExample.Plugins.Account.v5
{
    public class AccountPlugin : Kipon.Xrm.BasePlugin
    {
        public void OnPreCreate(Entities.Account.IPhonenumberChanged target, ServiceAPI.v3.IPhoneWashService washService)
        {
            washService.Wash(target);
        }

        public void OnPreUpdate(Entities.Account.IPhonenumberChanged target, ServiceAPI.v3.IPhoneWashService washService)
        {
            washService.Wash(target);
        }
    }
}

© Kipon ApS 2020, 2021, 2022, 2023. All content on the page is the property of Kipon ApS. Any republish or copy of this content is a violation. The content of this site is NOT open source, and cannot be copied, republished or used in any context without explcit permission from the owner.