All views and opinions are personal opinions of the Hosk

I recently did a YouTube video which stepped through the process of creating a simple CRM 2013 plugin which ran on the update of the account entity.

The purpose of the video was to step through the process of creating a plugin and with that in mind I wanted to create the simpliest plugin I could think of. Once you can do the process of creating a simple plugin and deploying it, it’s then a case of adding in your own logic and doing the process yourself.

This video updates the previous basic update plugin and this time I only trigger the plugin when a certain field Account Rating gets changed. This is important thing to consider in update plugins, particularly in these days of autosaving. Only trigger the plugin to run if certain fields are triggered, this will save server resources by not firing your plugin every 30 seconds.

It’s amazing the things you learn whilst writing blogs and recording videos. I didn’t previously know how you deleted plugins using the CRM Development toolkit, so I started sniffing about and then worked out how to. Below I run through changing the fields which trigger the account pre update plugin

Go to the CRM Explorer

You will notice the green plugins are the plugins in the solution you are in

nudge the down arrow and you can see the plugin steps

Edit the plugin step

The CRM Developer toolkit also allows you to delete the plugin or plugin steps, useful stuff

What’s passed into a plugin

The CRM 2013 SDK is a great document but a bit dry and difficult to get you started but once you are up and running there are lots of great explanations of how things work, this page is very useful for people writing plugins

It explains what is actually passed into the plugin, the ServiceProvider has lots of goodies in like

IPluginExecutionContext

This has lots of data in like the user who triggered the plugin

IOrganizationService

Use this to access CRM and Create, Read, Update and Delete CRM records

context.InputParameters and context.OutPutParameters

The input parameters hold a collection and in that collect is the Target entity object, this has the values changed from the account update

there is also the tracing object

In the example I am going to use all three of these item and in most plugins you will use them but the page also has this table which explains what objects are passed into the context.InputParameters because it’s not always the Target object you should look for. The picture below is a screenshot from the page

So what you should understand from the table above is, when a record or action triggers a plugin then usually either the entity is passed into the context.InputParameters or it’s an EntityReference. You usually retrieve and cast this object out and then pass this to your plugin logic.

The one that used to catch me out was SetStateRequest passing the EntityMoniker. What happened to me was I copied my boilerplate plugin code and I couldn’t understand why it wasn’t going into the code and running. The reason was I was checking to see if the Target existed and if it did casting it to an entity and passing that into another method to do the work but it never went into my code.

So I had to debug the code to find there was no Target! finally I found the oddly named EntityMoniker and I worked out what to do from there.

Plugin Stages

In the first plugin I couldn’t remember what the stages of a plugin were and their significance, all I could remember was they were linked to the database transaction and something about numbers going up in 10.

So I have done my homework and once again found some great information in the CRM 2013 SDK

The page has an interesting overview of the whole CRM architecture and it simplifies the stages

PRE-EVENT

PLATFORM CORE

POST-EVENT

The picture below is a screen from the Event Execution Pipeline page

As you know from registering plugins we can only register plugins

Pre-Validation – 10

Pre-Event – 20

Post-Event -40

The actually database transaction finishes in step 30 – Platform core operation and you can interfere with this, this is where the system plugins will run and kick off and updating system values and triggering other things.

An interesting point is the Pre-Validation, this is triggered before security checks have happened, so before CRM has checked the user can update the record maybe, basically before CRM checks the security roles and the PrincipalObjectAccess table (where all the security stuff is stored for users) is checked.

So that is the end of my quick plugin theory lesson and back onto the code, So along with the changing the plugin filter records (which you can see the RegisterFile.crmregister) I changed the code.

I now want to trigger the update on the change of AccountRating and I am going to read the value, which those of you who watched the video will know, OptionSetValue’s in CRM are held as ints. CRM also holds Metadata on the OptionSet which holds the text.

My code is going to run based on the Int value because I think maybe in the future people might change the text in the OptionSet from Gold, Silver, Bronze to 1, 2, 3 or Great, OK, Rubbish.

I also get the guid of the user (entity SystemUser)who triggered the plugin by updating the AccountRating field. This value is passed in with the plugin context and can be retrieved

Guid userId = context.InitiatingUserId;

There are two different user guid passed into the context and you should know which is which

I then lookup the fullname and domainname of the user because this is more useful than a guid to end users but the guid is great for retrieving more data about that record. I use the IOrganisationService to retrieve more fields from the record. To do this all I need is the entity logical name, guid and the fields I want to retrieve

// Note : you can register for more events here if this plugin is not specific to an individual entity and message combination.
// You may also need to update your RegisterFile.crmregister plug-in registration file to reflect any change.
}

/// <summary>
/// Executes the plug-in.
/// </summary>
/// <param name="localContext">The <see cref="LocalPluginContext"/> which contains the
/// <see cref="IPluginExecutionContext"/>,
/// <see cref="IOrganizationService"/>
/// and <see cref="ITracingService"/>
/// </param>
/// <remarks>
/// For improved performance, Microsoft Dynamics CRM caches plug-in instances.
/// The plug-in’s Execute method should be written to be stateless as 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. This means that you should not use global variables in plug-ins.
/// </remarks>
protected void ExecutePreAccountUpdate(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}