CRM 2016 – Maximum plugin size

Don’t watch the clock; do what it does. Keep going. Sam Levenson

Consistency is what separates the amateurs from the experts #HoskWisdom

Microsoft Dynamics CRM plugins have a maximum plugin size,  if you exceed this, the plugins will no longer import.

The limit is more likely to be hit in a CRM online projects because sandbox plugins can only include 1 dll, where CRM OnPremise projects can reference plugins in the GAC.

You can put common libraries in the GAC on the server.  I have worked in a project where we did this but it meant we had to install dll‘s onto multiple servers due to load balancing.  It worked but I’m not sure I liked this method and the majority of projects are being delivered with Microsoft Dynamics CRM online.

What is the plugin size?

I searched for the limit and it was difficult to find but I finally found this forum post

What is the maximum file size of plugin/workflow library in CRM?

The limit of the plugin is 8 Megabytes, this is a .NET limit on the httpRunTime MaxRequestLength setting held in the web.config.

Microsoft Dynamics CRM on premise projects can increase this value and I have had to do this before to import large solutions and reports

Why is this a problem?

The problem occurs when your solution is larger than 8 megabytes, you will get a timeout error.  For CRM online projects because you can’t increase  the setting without access to the web.config.

Early bound code can bloat plugins if you generate the early bound model for all entities and not just the ones you need.

Good practice is to limit the entities you create the early bound model for and you can do this with Early Bound Generator, available in the XRMToolbox

It doesn’t only affect CRM Online because the limit can happen for sandbox plugins in OnPremise deployments, highlighted in this article Import CRM Dynamics 2015 Managed Solution – Exceeded Content Size

What can you do

There are few options to avoid this

  • Limit the early bound classes to the entities referenced in the plugin
  • split your plugin into a separate solutions
  • don’t use global business logic classes, only include the business logic a group of plugin needs.

This might not be a problem but it should be something to be aware of, if your solutions are growing in size you will need to organise them into smaller solutions.

I talk about solutions organisation in this article CRM 2016 – What’s the best way to organise solutions in Microsoft Dynamics CRM

Advertisements

CRM 2015 – Why is the System user shown as disabled in the plugin registration tool

Someone asked me why the System user had the word disabled in brackets in the plugin registration tool when editing plugins and can we I still use it.

I have set plugins to run as SYSTEM but I couldn’t remember if the SYSTEM user had disabled in it. I fired up the plugin registration tool, selected a plugin, clicked the Run in User’s Context and found this

System User Disabled

I wasn’t sure whether I should be worried about the disabled or not, had it always been there?

In this example the CRM developer was setting a plugin to run as the SYSTEM user because the plugin need to run with more security privildges than the calling user.

To learn about Impersonation and plugins read my blog post

CRM 2015 – Understanding impersonation in plugins and knowing when to use it

What is the SYSTEM user

My knowledge of the SYSTEM user is it’s a super super in built user which you cannot see inside CRM in any of the views, the SYSTEM user won’t appear in disabled or enable user views inside CRM.

SYSTEM user is used by plugins, workflows to run with elevated privileges and when the user updates any records you will see SYSTEM.

Gonzalo Ruiz has written a great blog post on the SYSTEM and INTEGRATION

Explaining the built-in SYSTEM and INTEGRATION users

The blog post has a few interesting points to consider

  • Nobody can log in CRM as either of these 2 users.
  • These users are always on the root business unit.
  • No security applies to these users (any action is allowed when executing as SYSTEM or INTEGRATION), all security validations are bypassed.

I’m guessing the SYSTEM user shows this SYSTEM (disabled) to indicate the user is disabled from user CRM as a general user.

Why is named SYSTEM (disabled)?

SYSTEM (disabled) lets the CRM developer know they are selecting the special SYSTEM user and not a user created user who could also have the name SYSTEM.

I did check some other CRM instances (CRM 2011, CRM 2013 and CRM 2015) to see if SYSTEM always had SYSTEM (disabled) and in the three instances I looked at all had the words disabled in brackets after the SYSTEM user.

I’m not sure labelling the system user as disabled is the best idea because it caused concern we had somehow disabled the SYSTEM user or maybe we shouldn’t select it because it was disabled.

It seems it’s just Microsoft Dynamics CRM having a quirky way to indicate the SYSTEM user is special and not to be confused with other non super users (surely there is a better way)

CRM 2015 – How to diagnose plugin errors

failure-to-diagnose

This blog talks about a plugin error which I have seen a number of times when using the Plugin Developer Toolkit, it will discuss how to diagnose plugin errors in general.

Before I talk about plugins can I encourage people to vote on the connect item to get the CRM Developer toolkit working with Visual studio 2013, if you can’t wait for Microsoft to fix it then read my blog post CRM Developer Toolkit Alternatives

Hosk CRM Brain

I like to think of my blog as my CRM brain uploaded to the internet, so whilst reading this you are currently crawling through my CRM brain.  This allows me to search my CRM brain when my real brain forgets how I resolved a problem, actually sometimes I even forget I have experienced a problem and get pleasantly suprised when I have found not only did I have the problem before but I blogged the solution.

The benefit of me blogging about CRM is I benefit and other people who read and search my blog.

My goal in writing articles focused on errors is not only to write about how to resolve the issue but additionally look into the cause of the problem and , the WHY.

Knowledge helps when things go wrong

There is always a difference between theoretical knowledge and practical knowledge.   You can learn the theory of something but find it’s different when you try to use the theory in practical use (e.g. after reading about plugins you then try to write a plugin) you there are gaps in knowledge which you quickly find.

When developers start to plugins they usually go through

  • learn to write plugin code, find lots of errors
  • try to deploy plugin, error haven’t signed the plugin, error permissions etc.
  • Slowly but surely the developers experience fewer problems or problems they know how to resolve

Indepth knowledge of how Microsoft Dynamics CRM works and the underlying plugin infrastructure becomes extremely important when things go wrong.  When errors appear and hold up development, developers need to understand the cause of the error but why it’s complaining, the answer is usually understandable if you understand

  • how the CRM developer toolkit works
  • The various parts of the CRM Developer toolkit
  • The CRM plugin execution framework
  • The roles and privileges needed to deploy plugins

Some useful Hosk Plugin blog posts

The CRM developer toolkit is great (which is why I get annoyed it hasn’t been updated because it automates a lot of the repetitive actions needed to deploy a plugin using the plugin registration tool.) but I feel CRM Developers should learn how to use and deploy plugins using the plugin registration tool.

I use the plugin registration tool to inspect what plugins and steps are deployed and the ability to change the view to see what plugins are deployed for each entity is really useful when investigating bugs on CRM solutions you are not familiar with.

Most of the time you don’t want to mix using the plugin registration tool and the CRM developer toolkit because the CRM developer toolkit will overwrite the changes you make manually next a developer uses it to deploy CRM customizations.

The plugin registration tool is great for viewing the plugins deployed and its portability allows you to use it in customer environments.

If the CRM Developer toolkit gets in a mess you might need to use the plugin registration tool to quickly update or deploy a plugin whilst you fix the plugin developer toolkit.

I had an error previously but the problem was the CRM developer toolkit had got out of sync and I struggled to resolve this problem.  You can read about my frustrations with the CRM Developer toolkit

Dealing with Plugin errors

If When you experience a plugin error I would recommend you first read my blog on common problems because I cover the most common errors.

If you don’t find the answer then stop and think about the potential cause of the problem.  Many developers can go into a mild panic mode when they encounter an error, instead of logically thinking about the problem they instantly go and get a senior developer to help them.

Then when the senior developer is at their desk, they explain the problem.  The process of explaining the problem to the developer, the solution to the problem can become clear.  This is known as rubber ducking or I call this Cardboard developer

When you encounter a plugin problem or CRM developer problems, follow these steps

  1. Stop
  2. Engage Brain\Think
  3. What’s happening?
  4. What should happen?
  5. Make a list of the possible causes of the problem
  6. Investigate your list

If you can’t resolve the problem, you can then at tell the developer what you know, what you have tried.

I don’t encourage any developers to suffer in silence but it’s more beneficial for you own personal learning if you try to understand and resolve problems yourself.  The major benefit of trying to resolve the problem yourself is you get in the habit and become less dependent on the help of your colleagues.

Don’t Assume, know

Don’t Assume, Know is a Hosk mantra I tell myself when investigating problems or debugging.  I have wasted many hours investigating problems and looking for solutions based on an incorrect assumption.  When dealing with problems don’t assume anything, check assumptions and cross them off.  Lots of times you will find the problem.

Plugin Error Messages

The error messages Microsoft Dynamics CRM throws are a mixture of a confusing statement with a nugget of truth tucked inside.  To developers new to CRM development they are just unhelpful messages.

As your experience and knowledge of CRM development increases you will find they often point you in the right direction but you need to have built up a map of the CRM landscape, so you know where to go and check.

Plugin Error Example

This is common error I have experienced a few times but I was trying to deploy a plugin using the CRM developer toolkit and I got this error

Error registering plugins and/or workflows. Plug-in assembly does not contain the required types or assembly content cannot be updated.

Lets break down the message to try and decify the problem

  1. It can’t register the plugin/workflow
  2. Plugin Assembly does not contain required types or the assembly cannot be updated.
  3. So we know the plugin assembly (the DLL) exists but it cannot update it.

The first thing to do is know not assume.  So I opened the Plugin Registration tool and found the DLL.  I could see it had three steps.

I then looked at the RegisterFile.crmregister file and found this had two steps.

The problem was because we were trying to update an assembly with 2 steps but the assembly had 3 steps.  It couldn’t update the assembly because it was too different and this error message was letting us know (in a slightly confusing way).

I have experienced this problem before and the solution to the problem is to unregister the Assembly and install it again.

This problem has occurred when I have created new plugins and sometimes when I have updated a plugin maybe in a different solution but for some reason I couldn’t update the DLL.

In this case how the extra step got into the assembly was a complete mystery but it’s OK to delete the plugin assembly because I knew I was going to deploy it again and install a new version of the Plugin assembly.

CRM 2015 – How to decompile a plugin Assembly (DLL)

This blog post looks at how to decompile plugin code because I had a problem recently where I needed to do it.  The process will work in all version of CRM because fundamentally it works at DLL level rather than CRM level.

It’s a useful to understand because there are some instances where you need to know what code has been deployed because it might be different from the code you have or the code in your source control.

The problem – Why isn’t my fix working?

A bug fix I had deployed and tested in our dev environment and test environment suddenly stopped working when deployed to the customer environment.

This isn’t an unusual problem but an annoying one for developers.

Don’t assume, know

When bug fixing and testing try to avoid the trap of assuming because assumptions are often wrong, resulting in missing the obvious source of the problem, spending time testing other possible reasons for a problem.

Usually when a bug fails on a different environment I want to recreate it in the DEV environment where I can easily debug it.
For this problem we have two internal instances

DEV
TEST

I tested my fix in DEV and it seemed to work and then I tested the fix in internal TEST environment and found my fix didn’t work, why?

Finding the plugin code deployed

There are instances when you need to find the code deployed in a plugin. It’s possible to version plugins but CRM developers don’t bother versioning their plugins and I currently don’t version the CRM plugins.

Plugins can be versioned in the same way solutions are version in CRM

major.minor.build.revision

You need to think about versions and solutions because when you change the major number of a plugin assembly CRM considers it a completely different plugin assembly

Microsoft has a good article on Plugin Assembly

This article on how to upgrade version

Hardcore CRM: Do a major upgrade of a plugin version!

What to do if you don’t use assembly versioning

The problem I had was how could I tell what code was inside the plugin and if my fix was deployed?  The code in TFS (Source Control) was correct and up-to-date but I tested the functionality and could see it wasn’t working.

I decided to download the plugin assembly dll and decompile the code.

The tools I used was

XRMToolbox

Go to releases and click latest release if you want to download the application not the source
https://github.com/MscrmTools/XrmToolBox/releases

The XRMToolbox has a tool called Assembly Recovery Tool. This tool allows you to connect to a CRM instance, it loads all the assembly DLL’s (which can some time), you can choose to download any of the Plugin assemblys(dll file). This will give you the dll, which you can decompile using a different tool.

Once you have the DLL file you can decompile the dll using a tool such as

ILSPY

There are lots of other decompilers out and the main reason I use ILSPY is because its free

To use the decompiler you open it up, select a DLL or copy one to the application, below I have selected a HoskCRMDev2013 plugin.  The dll’s in blue are dependant plugins

decompile plugin

If you then click on one of the methods, it decompiles the code, which you can view it in the yellow right hand screen.

decompile plugin1

ILSPY has a few neat options to save the to file.

A few notes on decompiling DLLS

DONT decompile DLL’S you or the company you work for doesn’t own because basically you are viewing the source code.

I’m not sure about the legality of it but it’s probably illegal, particularly if you don’t own the intellectual property.

If you aren’t sure if you should decompile a DLL think about it like this.  If you went to the owner of the source code and asked to view the source code, would they let you?

A common cause of decompiling plugins/custom workflows is to see what has been deployed if plugin versioning is not used.

Be warned decompiled code is slightly different, often the variables don’t have the same name.

If you are concerned about your dlls being decompiled there is a tool to encrypt them, I haven’t used it.  The discussion on StackOverflow is a good place to start if you are interested

Protect .NET code from reverse engineering?

When might you need to decompile a DLL?

Surprisingly there are quite a few scenarios where you might need to decompile a DLL, I will go through some of the common scenarios but the

Lost source control

I have seen scenarios where a company has lost the source control for code which has been deployed.  Often its old legacy systems and most people who worked on the project have left the company

Deployed with source control checked out pending

A developer deploys some code, forgets to check in the code.  The developer then might leave the company, go on holiday and can’t be contacted.  You need to know what code has been deployed and what code might not be checked it.

Plugin won’t deploy from CRM Developer toolkit

Sometimes a plugin won’t deploy and you will get an error like this

Error registering plugins and/or workflows. Plug-in assembly does not contain the required types or assembly content cannot be updated

The reason for this error is often because the deployed assembly file (DLL) is different.  It might have an extra step and you are not updating the file but trying to replace it.  CRM doesn’t like this.

I had an example of this recently and there was an additional step in the deploy DLL.  I used the plugin registration tool to compare the steps but I wasn’t sure what was in the extra step.  So I download the DLL and looked at the code.

What has been deployed

This is the problem I was experiencing for this bug.  I needed to check if the code deployed was the same as the code in source control, the only way I could do it was to decompile the code and compare.

Plugins without versioning

A common cause of decompiling plugins/custom workflows is to see what has been deployed if plugin versioning is not used.

Multiple Developers Versus Source Control

When you have multiple developers working on a project, source control can sometimes lead to problems with people not getting the latest code and deploying an older version

Who deployed the different plugin?

I was wondering how the different plugin version got deployed. I wondered if I could work out what solutions were imported

I remember review a useful tool a while ago the Solution History tool, which is a tool which works with the XRMToolbox

You can download the tool here

The tool usefully told me what solutions had been imported and what files were included.

I could see the solution had been changed and who imported but I couldn’t tell what version of the Plugin Assembly had been deployed.

This tool would be extremely useful if the project you are working on imports multiple solutions without changing the version number.

What gets updated when you import a plugin to the database?

In the background when you import a plugin it updates system entity called plugin. I wondered if I could select these entities to see when they had been updated.

The problem is you can’t select system entities in an advanced find, so I remember another tool which works with the XRMToolBox the FetchXML Builder

You can get the tool here

This tool is useful because it has GUI interface to allow you to create Fetch XML queries. This means you can select system records.

The real beauty of this is you can create FetchXML queries and then use them in your plugins.

I wanted to use the tool to easily query the system entity of plugin

retrieve plugin

Which produces the FetchXML below

<fetch count ="50 " >
<entity name ="pluginassembly " >
< filter>
< condition attribute= "name" operator=" eq" value ="Full Assembly Name " />
</ filter>
</entity>
</fetch>

This allowed me to retrieve when the plugin was changed and by who. I was wondering if someone had directly deployed a plugin to the Test environment and bypassing the Solution import phase but it turned out not to be the case.

I couldn’t work out who had deployed an old plugin version and the important point was I had the resolution to the problem (although you would like to be confident it wouldn’t happen in the future)

Summary

This blog should show you how to download and decompile a DLL file.  There are certain scenarios where you aren’t sure if the code deployed is the same as the code in your source control.

Downloading and decompiling DLL’s is another tool to put in your development bag, make sure you use it for good not evil.

CRM 2013 – Workflow error AccessCheckEx

I was investigating a bug on CRM 2013 , I got the exception below

Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: SecLib::AccessCheckEx failed. Returned hr = -2147187962, ObjectID: f115e97d-8e19-e511-80ca-000c292122be, OwnerId: 89ed0bdd-7ecd-e411-80c7-000c292122be,  OwnerIdType: 9 and CallingUser: 2ed69167-0bcf-e411-80c7-000c292122be. ObjectTypeCode: 4200, objectBusinessUnitId: 5f964320-05f4-e411-80c9-000c292122be, AccessRights: WriteAccess Detail:
<OrganizationServiceFault xmlns:i=”http://www.w3.org/2001/XMLSchema-instance&#8221; xmlns=”http://schemas.microsoft.com/xrm/2011/Contracts”&gt;
  <ErrorCode>-2147220891</ErrorCode>
  <ErrorDetails xmlns:d2p1=”http://schemas.datacontract.org/2004/07/System.Collections.Generic”&gt;
    <KeyValuePairOfstringanyType>
      <d2p1:key>OperationStatus</d2p1:key>
      <d2p1:value xmlns:d4p1=”http://www.w3.org/2001/XMLSchema&#8221; i:type=”d4p1:string”>0</d2p1:value>
    </KeyValuePairOfstringanyType>
    <KeyValuePairOfstringanyType>
      <d2p1:key>SubErrorCode</d2p1:key>
      <d2p1:value xmlns:d4p1=”http://www.w3.org/2001/XMLSchema&#8221; i:type=”d4p1:string”>-2146233088</d2p1:value>
    </KeyValuePairOfstringanyType>
  </ErrorDetails>
  <Message>SecLib::AccessCheckEx failed. Returned hr = -2147187962, ObjectID: f115e97d-8e19-e511-80ca-000c292122be, OwnerId: 89ed0bdd-7ecd-e411-80c7-000c292122be,  OwnerIdType: 9 and CallingUser: 2ed69167-0bcf-e411-80c7-000c292122be. ObjectTypeCode: 4200, objectBusinessUnitId: 5f964320-05f4-e411-80c9-000c292122be, AccessRights: WriteAccess </Message>
  <Timestamp>2015-06-23T10:02:24.458209Z</Timestamp>
  <InnerFault i:nil=”true” />
  <TraceText>

[Microsoft.Crm.ObjectModel: Microsoft.Crm.ObjectModel.SyncWorkflowExecutionPlugin]
[0dac4467-fb18-e511-80ca-000c292122be: ]
Starting sync workflow ‘Task-Workflow’, Id: 04ac4467-fb18-e511-80ca-000c292122be
Entering ConditionStep1_step: If  Process contains data and is active
Entering SetStateStep4_step: Change record status to completed
Sync workflow ‘Task-Complete’ terminated with error ‘SecLib::AccessCheckEx failed. Returned hr = -2147187962, ObjectID: f115e97d-8e19-e511-80ca-000c292122be, OwnerId: 89ed0bdd-7ecd-e411-80c7-000c292122be,  OwnerIdType: 9 and CallingUser: 2ed69167-0bcf-e411-80c7-000c292122be. ObjectTypeCode: 4200, objectBusinessUnitId: 5f964320-05f4-e411-80c9-000c292122be, AccessRights: WriteAccess ‘
</TraceText>
</OrganizationServiceFault>

Initial thoughts on the Error

I got this error and there were a few things I found interesting

This error was surprisingly informative

The error was thrown by a non code workflow but the cause of the error was thrown by a GUI workflow which was being triggered when a workflow tried to assign an activity.

I was impressed by the level of logging which was generated by a GUI/non code workflow.

I had never thought about it but this line

Microsoft.Crm.ObjectModel: Microsoft.Crm.ObjectModel.SyncWorkflowExecutionPlugin

indicates CRM runs the GUI workflows using code, which must translate the actions into code. This is obvious but I hadn’t thought about it, until seeing the error.

You can use the callerid to find what user is doing the update and check what security roles the user has.

EntityTypeCode

In the error message you can see it mentions ObjectTypeCode

CRM 2011/2013 – Javascript to get the object type code of an entity

Each entity has an individual typecode, this CRM SDK page shows you the values of the default entities

Entity Type Code 4200 is ActivityPointer, which is interesting because the problem was being caused by an update to a task record.

Clues

AccessCheckEx failed – AccessCheckEx is something to do with security and access

In the error message you can see

AccessRights: WriteAccess

This is clearly telling us the user doesn’t have Write access, e.g. the user isn’t allow to update a certain

What was the cause

This bug was partly caused by the complexity of the CRM solution and the different customizations.

Solution complexity refer to not only the customizations which exist in the solution but the number of different customizations.  When a CRM solution has lots of different customizations e.g. workflows, plugins, business rules being triggered at the same time it makes it difficult to understand what is changing a value.

Below is what was happening

  1. A task was updated then saved
  2. This triggered a pre plugin on the task entity
  3. The plugin assigns the case record
  4. A plugin was triggered on assign of the case, which assigned all the open tasks to the new case owner
  5. The plugin(s) finished
  6. A workflow was triggered, which tried set the task to complete.

The error was thrown because the workflow was trying to update the task but the user only had privileges to update tasks they owned.

The reason this bug suddenly appeared was because the assign plugin was added and it wasn’t picked up in DEV testing because developers tested the code using users with System Admin privileges, which I have talked about before

The System Administrator role is a benefit and a curse to CRM developers

It’s tricky to test the effect of adding plugins

Having lots of different types of customizations adds to the complexity of your CRM solution, complex solutions are difficult to debug, understand and extend.

The Solution

Usually with bugs where the user doesn’t have the right security privilege the easy answer is to give the user role those security privileges.

For this bug it wasn’t the correct solution because the users only had access to tasks they owned and we didn’t want to suddenly give them permissions to update tasks they didn’t own.

The plugin code was running in a PRE plugin, so I couldn’t move the task completing code into this plugin.

The bug was becoming more tricky because I did want to keep the case assigning code in their but I didn’t want the assigning case plugin to run and assign the task to the new case owner because the task was about to completed.

My solution was to stop the assign plugin being triggered if was called by another plugin

Read how to do that in the blog below

CRM Plugins – Stopping infinite loops and understanding PluginExecutionContext.Depth

I then created a post task plugin to complete the task.  I didn’t need to do this but it seemed it would be easy to understand if all the changes were made by plugins.

There was an unsuccessful fix when I used impersonation to close the task as System Admin but the users didn’t like the tasks being closed by System Admin, they wanted the user who updated the task to complete the task.

You can read about Impersonation in plugins in the blog post below

CRM 2015 – Understanding impersonation in plugins and knowing when to use it

CRM 2015 – Understanding impersonation in plugins and knowing when to use it

Plugins are usually set to run as the calling user but sometimes you need to run a plugin with System User privileges.

Before I explain how, we should first look at the why and how you impersonate users inside a plugin

I have been writing a bit about plugins recently

For some step by step guides to creating plugins check out the CRM Code examples section on the page Hosk’s CRM Developer Articles, I created some Youtube videos CRM 2013 Plugins

What is impersonation

When you create a plugin in CRM (step by step blog post here) you write an execute method which gets passed in

IServiceProvider serviceProvider

This has lots of variables and objects such as

  • IPluginExecutionContext
  • ITracingService
  • IOrganizationServiceFactory

You use the IOrganisationServiceFactory to create a IOrganizationService.  The IOrganizationService is the CRM SDK, it provides you access to CRM programmatically .  CRM developers use the IOrganizationService (which I will often call CRMService) to

  • CRUD operation – Create, Retrieve, Update, Delete records in CRM
  • Assign records
  • Change status
  • pretty much everything you can do in CRM

Here is the code to create the IOrganizationService, taken from the Plugin class of the CRM Dev toolkit

// Obtain the Organization Service factory service from the service provider
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

// Use the factory to generate the Organization Service.
this.OrganizationService = factory.CreateOrganizationService(this.PluginExecutionContext.UserId);

When creating your plugin you will notice there is a Run in Context setting, most of the time you will choose to Run In Context of Calling User.

Create Account Plugin 1

99 percent of the time Calling User is the right choice

It’s usually the right choice to use the Calling User because any updates, retrieves or any interaction with CRM data will be done using the calling users identity and privileges.

If you visualize a plugin as an automated extension of the CRM form, it’s likely you want the the code in the plugin to run with security privileges as the calling user.  It allows you not to abdicate the need to apply security to the plugin code and pass this off the users security profile and CRM.

The PluginExecutionContext (which I explain in this blog post) has the field called UserId.  We pass this to the IOrganizationFactory to create an IOrganizationService with the user who initiated the plugin.  The good news is the CRM Dev toolkit does all this for us, so we can just chill out and get the IOrganizationService and work on the business logic.

// Use the factory to generate the Organization Service.
this.OrganizationService = factory.CreateOrganizationService(this.PluginExecutionContext.UserId);

Running the CrmService (IOrganizationService) as the calling user means you are interacting with the data in CRM as the calling user, which means

  • The IOrganizationService can only retrieve data the user can retrieve
  • When IOrganizationService updates, creates records they are stamped with the calling user
  • The plugin cannot do anything the calling user cannot do

The calling user setting adheres to the security role assigned to the calling user, integrity of your precious CRM data is kept intact.

Why impersonate System User

If running plugins as the calling user is so good, why impersonate other users or system admins.

  • What if you need to retrieve records the user doesn’t have access to?
  • What if you need to update records the user doesn’t have access to?

You might be thinking, “if the user doesn’t have access to those records, maybe the plugin shouldn’t be updating them”.

It’s a point to consider point but sometimes you want to create records or update records based on the action/status of an entity to move the code to the next stage/state.

Sometimes you want to assign a record to another user when a record goes to a certain state but you wouldn’t want users to be able to assign records.

How is running in context different from impersonation

The running in context setting on a plugin mentioned early runs the whole plugin in that context.

Impersonation allows you to run a small section of code in another context.

Impersonation gives the CRM developer more flexibility to target a particular action in a plugin they would like to run with elevation permissions.  The rest of the plugin actions can be run as

Dangers of impersonation

The downsides of impersonation is it potentially gives users running the plugin\custom workflow enhanced security privileges which could lead who we don’t want updating\deleting records doing exactly that.

When using impersonation in plugins consider accountability and audit trails.  When a plugin impersonates a system user or a different user, the impersonated user will update those records.  It can be confusing/worrying for users when looking at audit records to see System Admin updating records.

I’m sure there have been thousands of support calls querying why System Admin has been updating records.

Impersonation Code

Easy way to impersonate System User is to pass null to the CreateOrganizationService and it will run as System user, find out more in this CRM SDK article

// Use the factory to generate the Organization Service.
OrganizationServiceImpersonated = factory.CreateOrganizationService(null);

You can pass in a different user Id to the CreateOrganizationService to create an IOrganizationService

IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.InitiatingUserId);

The sample code in the CRM SDK article impersonates using OrganizationServiceContext.  I personally have used this

Sample: Impersonate using the ActOnBehalfOf privilege

// Retrieve the system user ID of the user to impersonate.
OrganizationServiceContext orgContext = new OrganizationServiceContext(_serviceProxy);
_userId = (from user in orgContext.CreateQuery&lt;SystemUser&gt;()
where user.FullName == "Kevin Cook"
select user.SystemUserId.Value).FirstOrDefault();

// To impersonate another user, set the OrganizationServiceProxy.CallerId
// property to the ID of the other user.
_serviceProxy.CallerId = _userId;

Impersonating during plugin-in registration

You can impersonate a user during plugin-registration but I’m not entirely sure why you would do this, so I’m not going to talk about.  Most CRM developer will impersonate someone inside a plugin.

If you want to learn more read

Impersonate another user

and the articles in the futher reading section

Why, What, Where, When

What is Impersonation

Impersonation in plugins/custom workflows is creating an IOrganisationService as a different user

Why use Impersonation

Use impersonation when you need to update/retrieve/delete/Create records users security roles doesn’t let them.

Where

If you don’t want to increase users security roles but still want the plugin to do a particularly action.  e.g. delete a record

When

You use impersonation in plugins/customer workflows

Further reading

Scott Durow has an excellent article on Impersonation

User Impersonation in Plugins, Workflow and Dialogs

CRM SDK 2015 impersonating User in plugins

Dave Berry does a good job explaining Impersonation – CRM Impersonation Explained

Awesome Pixar impersonation picture from here

FetchXML reports do not trigger RetrieveMultiple plugins in CRM 2011

 

It is by going down into the abyss that we recover the treasures of life. Where you stumble, there lies your treasure.
Joseph Campbell

The CRM forums are a great resource for learning interesting solutions and problems in Microsoft Dynamics CRM

I read this interesting gotcha/CRM Quirk this week about a CRM developer who had written a plugin which was triggered on the RetrieveMultiple event on his custom entity.  The user was wondering why his plugin was not being triggered when the user ran a report using FetchXML.

RetrieveMultiple Plugins, What, Why and How?

So you can have plugins which trigger on RetrieveMultiple for an entity.  Some readers are thinking why would you want to do that?

Reasons like

  • Translate data held in the CRM database
  • Exclude data from RetrieveMultiple queries
  • Log RetrieveMultiple requests
  • Calculate some fields in the retrieve from other entities
  • Decrypting encrypted fields

There are lots of other reasons, but they give you an idea.  The user wouldn’t even know a plugin had run because they would just receive the results as normal.

The retrieve multiple is triggered in CRM when the user

  • Runs an advanced find
  • User clicks on a view (e.g. active accounts)
  • Quick search
  • Associated views
  • Plugins doing retrieve multiples
  • Console apps doing retrieve multiples

 

What about reports and FetchXML

So why don’t reports and FetchXML trigger the RetrieveMultiple plugin

The answer was explained in this forum post answer by CRM legend David Jennaway who is a CRM MVP, when I was starting in CRM development David had a fantastic CRM blog which I followed avidly and still do, but but unfortunately for the CRM community David rarely writes any blog posts these days (2 post in 2014).

Reports do not trigger plugins. SQL reports bypass CRM completely, and Fetch reports also bypass the plugin pipeline
 He also add this answer
Just to clarify the last post, in CRM 2011 fetch queries are submitted via the RetrieveMultiple message, whereas in CRM 4 they were submitted via the Fetch message and (bizarrely) you could handle them in plugins on the Execute message
This logically makes sense because SQL reports definitely would hit the plugin pipeline and I’m guessing FetchXML when run from reports must be run using a slightly different mechanism (I have no knowledge of this)
I’m not sure if this is the same in CRM 2013 but I’m guessing it’s probably going to be the same because I don’t think there have been changes in those areas of functionality.