IPluginExecutionContext
can be considered the heart of a plug-in assembly because it supplies all the required information to the plug-in. It contains all the CRM context information, such as the entity the plug-in is executing, the user who is responsible for plug-in execution, and various input and output parameters with other related information. We can get IPluginExectuionCotext
from IServiceProvider
, as follows:
public void Execute(IServiceProvider serviceProvider) { // Obtain the execution context IPluginExecutionContext context = (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext)); }
It contains many members that help us to get information for our plug-in. The following are the most used members of IPluginExecutionContext
:
You can refer to https://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.ipluginexecutioncontext_members.aspx for more details on IPluginExecutionContext
members.
In order to perform operations on data and metadata we need to get organization services. We can get the organization service object from IServiceProvider
using the following code:
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
In the preceding code, we are getting the IOganizationService
object by passing the current user ID, but if we pass a null value to the CreateOrganizationService
method then the IOgranizationService
object is created using the system user account, which has all privileges.
We can also impersonate the user using the code instead of the plug-in registration tool that we discussed earlier. To impersonate the user we can simply use the following code, after creating the organization service object. After using the following statement, the CRM will be reacting on the entire request based on the current user ID instead of the user used for authentication:
serviceProxy.CallerId = new Guid("GUID of the user");
But keep in mind that impersonation is only possible if the user has the Act on Behalf of Another User privilege; by default this privilege is configured in the Delegate security role, so in our case the authenticated user should have this security role assigned or should have the Act on Behalf of Another User privilege configured in their role.
You can also refer to: https://www.develop1.NET/public/post/User-Impersonation-in-Plugins-Workflow-and-Dialogs.aspx to get more information about impersonation.
The input argument collections store all the data modified by the user and other entity information. Input argument collection is available by using context; we can get it using the following line of code:
context.InputParameters["Key"]
But every message has its own input and output parameters; what information is available on the input parameter and how we can get it are completely dependent on the plug-in message. So, for example, in the case of the create
plug-in on the account entity, we will get Target
as a key, so we can use the following to get the entity object:
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { Entity entity = (Entity)context.InputParameters["Target"]; }
You can refer to a list of input and output parameters here: http://www.patrickverbeeten.com/Blog/2008/01/25/CRM-40-Plug-in-message-input-parameters. Although CRM 4.0 is referenced here, it's the same for CRM 2015.
It is always recommended that you first check the availability of the key using the Contains
method and throwing an error if it's not available under the property beg instead of directly accessing it. After that we can get the entity object as earlier. If we have a requirement to write a plug-in on the setstage
message we won't get Target as a key; instead we will get EntityReference
as follows:
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is EntityReference) { EntityReference entityReference = (EntityReference)context.InputParameters["Target"]; string entityName = entityReference.LogicalName; }
Similarly, output operations can be obtained from context depending on the message used; for example in the case of create, we can get the record ID from the output parameters as follows:
if (context.OutputParameters.Contains("id")) { Guid AccountId = context.OutputParameters["id"]; }
Sometimes, while working on business logic we may need to share variables between plug-ins because we don't want to store these values in the CRM database; instead we can store them in an entity and can read from that entity. We have the option available to share data between plug-ins using shared variables. Shared variables are basically collections of key-value pairs that can be added in one plug-in and can be collected from another plug-in:
Let's take an example where we have pre- and post-plug-ins on the account entity, and we have some logic to check if approval is required for the account. So we can use the following code to add shared variables in our pre-create account plug-in:
context.SharedVariables.Add("ApprovalRequired", true);
Now in our post plug-in we can simply check if any shared variable exists under context; if yes, we can get it as follows:
if (context.SharedVariables.ContainsKey("ApprovalRequired")) { bool isApprovalRequired = (bool)context.SharedVariables[ "ApprovalRequired"]; }
Plug-in images allow us to capture specific or all fields of an entity on some events. They help us to get the entity field value before or after changes. We can register pre and post images in our plug-in. Which image we can use in our plug-in depends on the message. For example we can't register pre images on create messages and similarly we can't use post images for delete messages, but in update message we can use both pre and post images. So, for example, it may be that we want to keep a copy of the data before an update event and want to compare it with the data available after the update event. So we can register both pre and post images and do a data comparison between them. It is recommended that you get data from plug-in images instead of making service calls and getting it from the CRM database.
Plug-in images are registered after registering the step using Register New Image. We can store all entity fields under plug-in images, but it is recommended that you store only required fields to improve plug-in performance. We can select fields by clicking on the ellipse (…) next to the Parameters textbox:
Once the image is registered, we can access it using the input property beg as in the following code:
if (context.PreEntityImages.Contains("Pre")) //name of the //Entity Alias used { Entity preImage = (Entity)context.PreEntityImages["Pre"]; }
Now we can get fields from the preImage object just like we can get them from the entity object, as in the following code:
if(preImage.Contains("address1_city")) { string city = preImage.GetAttributeValue<string>("address1_city"); }
18.222.116.146