0% found this document useful (0 votes)
82 views24 pages

Plugins in Dynamics CRM

The document provides a comprehensive guide on creating and registering plugins for Microsoft Dynamics CRM, detailing the steps for implementing custom business logic that responds to specific events. It covers the plugin execution pipeline, including stages like Pre-Validation, Pre-Operation, and Post-Operation, as well as the differences between synchronous and asynchronous plugins. Additionally, best practices for writing efficient plugins, error handling, security considerations, and performance optimization techniques are discussed.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
82 views24 pages

Plugins in Dynamics CRM

The document provides a comprehensive guide on creating and registering plugins for Microsoft Dynamics CRM, detailing the steps for implementing custom business logic that responds to specific events. It covers the plugin execution pipeline, including stages like Pre-Validation, Pre-Operation, and Post-Operation, as well as the differences between synchronous and asynchronous plugins. Additionally, best practices for writing efficient plugins, error handling, security considerations, and performance optimization techniques are discussed.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 24

Plugins

Definition :
A Dynamics CRM plugin is custom business logic or code that integrates with Microsoft Dynamics
CRM to modify or extend the standard behaviour of the platform. Essentially, plugins act as event
handlers and are registered to execute in response to specific events, such as creating, updating, or
deleting records.

Creating First Plugin :


Let’s walk through the process of creating a simple plugin that triggers on the creation of a new

account record and updates a custom field.

1. Create a New Class Library Project in Visual Studio:

o Open Visual Studio and create a new project. Select Class Library and name it

MyFirstPlugin.

2. Add Necessary References:

o Add references to the Microsoft.Xrm.Sdk and Microsoft.Crm.Sdk.Proxy assemblies.

These can be found in the SDK’s bin folder.

3. Implement the IPlugin Interface:

o Create a new class that implements the IPlugin interface. This interface requires you

to implement the Execute method.

using System;

using Microsoft.Xrm.Sdk;

namespace MyFirstPlugin

public class AccountPlugin : IPlugin

public void Execute(IServiceProvider serviceProvider)

// Obtain the execution context from the service provider.

IPluginExecutionContext context =

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

// The InputParameters collection contains all the data passed in the message request.

if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is


Entity)

// Obtain the target entity from the input parameters.

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

// Verify that the target entity represents an account.

if (entity.LogicalName != "account")

return;

// Update a custom field.

entity["new_customfield"] = "Plugin executed!";

4. Build the Project:

o Build the project to generate the assembly (DLL file).

Registering Plugins Using Plugin Registration Tool

Now that you have created your first plugin, the next step is to register it with Dynamics 365 CE
using

the Plugin Registration Tool.

1. Open the Plugin Registration Tool:

o Connect to your Dynamics 365 CE instance.

2. Register the Assembly:

o Click on Register > Register New Assembly.

o Browse to the DLL file generated from your Visual Studio project and select it.

o Enter a name and description for the assembly and click Register.

3. Create a Step:

o After registering the assembly, you need to create a step that specifies when the

plugin should execute.

o Right-click on the newly registered assembly and select Register New Step.

o Fill in the details, such as the message (e.g., Create), primary entity (e.g., account),

and execution stage (e.g., Post-Operation).


o Click Register New Step to complete the registration.

Plugin Execution Pipeline


The plugin execution pipeline determines the order in which plugins and other operations are
executed in response to an event. Understanding the pipeline is crucial for developing effective
plugins.

• Pre-Validation Stage:

o Runs before any security checks and the main operation.

o Useful for custom validation logic.

o Executes outside the database transaction, meaning changes made here are not

rolled back if the main operation fails.

It supports only for synchronous plugins

• Pre-Operation Stage:

o Runs after validation but before the main operation.

o Ideal for modifying input data before it is processed.

o Executes within the database transaction, so changes are rolled back if the main

operation fails.

It supports only for synchronous plugins

Main Operation:

o The core operation, such as creating, updating, or deleting a record

• Post-Operation Stage:

o Runs after the main operation has completed.

o Suitable for actions dependent on the results of the main operation, such as sending

notifications or updating related records.

o Executes within the database transaction

It supports Both synchronous and asyncronous plugins

Synchronous vs Asynchronous Plugins


Plugins can be executed synchronously or asynchronously, depending on the business requirements

and performance considerations.


• Synchronous Plugins:

o Execute immediately and block the main operation until the plugin completes.

o Suitable for scenarios where immediate processing is required.

o May impact performance if the plugin logic is complex or time-consuming.

• Asynchronous Plugins:

o Execute in the background without blocking the main operation.

o Ideal for operations that do not require immediate execution, such as sending emails

or performing batch updates.

o Improve system performance by offloading processing to background tasks.

Writing Efficient Plugins


Efficiency is crucial for ensuring that plugins do not degrade system performance. Here are some
best

practices for writing efficient plugins:


1. Minimize Resource Usage:

o Use the Service Locator pattern to instantiate required services only when needed.

o Avoid retrieving more data than necessary.

2. Optimize Queries:

o Use fetch XML or QueryExpression to retrieve only the required fields.

o Implement paging for large data sets.

3. Use Caching:

o Cache frequently accessed data to reduce repeated calls to the database.

4. Avoid Long-Running Operations:

o Offload long-running tasks to asynchronous plugins or background services.

Error Handling and Logging

Proper error handling and logging are essential for diagnosing issues and ensuring reliable plugin

execution.

1. Implement Robust Error Handling:

o Use try-catch blocks to handle exceptions.

o Provide meaningful error messages to help diagnose issues.

2. Use Tracing and Logging:


o Utilize the ITracingService to log detailed information about plugin execution.

o Implement custom logging to track plugin performance and errors.

3. Graceful Degradation:

o Design plugins to handle failures gracefully, ensuring that the main operation can

continue if possible.

Security Considerations
Security is a critical aspect of plugin development. Here are some key considerations:

1. Avoid Hardcoding Sensitive Information:

o Use secure and unsecure configuration parameters to store sensitive data.

2. Validate User Input:

o Ensure that all user inputs are validated to prevent security vulnerabilities such as

SQL injection.

3. Implement Role-Based Security:

o Check user roles and permissions before performing operations to ensure compliance

with security policies.

Performance Optimization
Optimizing plugin performance is essential for maintaining system responsiveness and user

satisfaction.

1. Profile and Analyze Plugins:

o Use profiling tools to identify performance bottlenecks.

o Analyze plugin execution times and optimize code accordingly.

2. Optimize Database Access:

o Reduce the number of database calls by batching operations where possible.

o Use appropriate indexes to speed up data retrieval.

3. Leverage Asynchronous Execution:

o Offload non-critical operations to asynchronous plugins to improve overall system

performance.
Working with Secure and Unsecure Configuration
Plugins can be configured with secure and unsecure configuration data, providing flexibility
in managing sensitive information.

1. Secure Configuration:

o Accessible only to users with the System Administrator role.

o Use for storing sensitive data, such as connection strings or credentials.

2. Unsecure Configuration:

o Accessible to all users.

o Use for storing non-sensitive data, such as plugin settings or thresholds.

Example for Unsecure configuration Plugin (Show hide Views based On BU):
using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using System.Runtime.Serialization.Json;

using System.Text;

using Microsoft.Xrm.Sdk;

using Microsoft.Xrm.Sdk.Messages;

using Microsoft.Xrm.Sdk.Metadata;

using Microsoft.Xrm.Sdk.Query;

namespace Plugins

public class ShowHideQueueItemViewsBasedOnBU : IPlugin

#region Secure/Unsecure Configuration Setup

private string _secureConfig = null;

private string _unsecureConfig = null;

public ShowHideQueueItemViewsBasedOnBU(string unsecureConfig, string secureConfig)


{

_secureConfig = secureConfig;

_unsecureConfig = unsecureConfig;

#endregion

public void Execute(IServiceProvider serviceProvider)

IPluginExecutionContext context =
(IPluginExecutionContext)serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionCon
text));

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

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

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

QueryExpression query = null;

string userBUName = string.Empty;

EntityReference adminuser = FetchRecord(service, tracer);

IOrganizationService adminUserService =
serviceFactory.CreateOrganizationService(adminuser.Id);

try

tracer.Trace("Plugin started... ");

if (context.MessageName.Equals("RetrieveMultiple"))

tracer.Trace("Depth: " + context.Depth);

Entity user = service.Retrieve("systemuser", context.UserId, new


ColumnSet("businessunitid", "fullname"));

if (user != null)

userBUName = user.Attributes.Contains("businessunitid") ?
user.GetAttributeValue<EntityReference>("businessunitid").Name : string.Empty;

Entity UserEntity = new Entity(user.LogicalName, user.Id);

UserEntity["cap_lastaccesstime"] = DateTime.Now;
tracer.Trace("User Name: " + user.Attributes["fullname"].ToString().ToUpper());

if (user.Attributes["fullname"].ToString().ToUpper() != "SYSTEM" &&


user.Attributes["fullname"].ToString().ToUpper() != "INTEGRATION")

adminUserService.Update(UserEntity);

tracer.Trace("lastaccesstime stamped");

if (context.InputParameters.Contains("Query") && context.InputParameters["Query"] is


QueryExpression)

query = (QueryExpression)context.InputParameters["Query"];

tracer.Trace("entity Name" + query.EntityName);

if (query.EntityName == "savedquery")

if (query.Criteria != null && query.Criteria.Conditions != null)

RetrieveEntityRequest retrieveEntityRequest = new RetrieveEntityRequest

EntityFilters = EntityFilters.Entity,

LogicalName = "queueitem"

};

RetrieveEntityResponse retrieveAccountEntityResponse =
(RetrieveEntityResponse)service.Execute(retrieveEntityRequest);

EntityMetadata queueItemEntity =
retrieveAccountEntityResponse.EntityMetadata;

int entityTypeCode = (int)queueItemEntity.ObjectTypeCode;

var rtcCondition = query.Criteria.Conditions.SingleOrDefault(c =>


c.AttributeName.Equals("returnedtypecode"));

if (rtcCondition == null) return;

int returnedtypecode = (int)rtcCondition.Values[0];

tracer.Trace("returnedtypecode: " + returnedtypecode);


//Return if entity code is other than queueitem

if (returnedtypecode == entityTypeCode)

if (!string.IsNullOrWhiteSpace(userBUName))

List<BUAndViewsMapping> buAndViewsMapping =
ReadUnsecuredConfigStringToObject(_unsecureConfig);

if (buAndViewsMapping != null && buAndViewsMapping.Count > 0)

BUAndViewsMapping buRecord = buAndViewsMapping.Where(a =>


a?.BUName?.ToLower() == userBUName.ToLower()).FirstOrDefault();

ConditionExpression queryCondition = null;

if (buRecord != null && !string.IsNullOrWhiteSpace(buRecord.BUName) &&


buRecord.Views.Count > 0)

queryCondition = new ConditionExpression("name",


ConditionOperator.In, buRecord.Views.ToArray());

query.Criteria.Conditions.Add(queryCondition);

tracer.Trace("Filter criteria applied on QueueItem");

else

tracer.Trace("BU record not found in unsecured config");

else

tracer.Trace("Unsecurred config in JSON missing");

else

string[] treatmentViews = new string[] { "" };

string[] allergyViews = new string[] { "" };

string[] conditionViews = new string[] { "" };


string[] familyHistoryViews = new string[] { "" };

string[] SAOViews = new string[] { "" };

string[] socialActivityViews = new string[] { "" };

string[] alcoholViews = new string[] { "" };

EntityCollection SMHviews = FetchApplicationParameter(service, tracer);

for (int i = 0; i < SMHviews.Entities.Count; i++)

string parameterName =
SMHviews.Entities[i].Contains("cap_parametername") ? SMHviews.Entities[i]
["cap_parametername"].ToString() : string.Empty;

if (parameterName == "Entity Views - Treatment")

string treatment = SMHviews.Entities[i].Contains("cap_parametervalue") ?


SMHviews.Entities[i]["cap_parametervalue"].ToString() : string.Empty;

treatmentViews = treatment.Split(',');

else if (parameterName == "Entity Views - Allergy")

string allergy = SMHviews.Entities[i].Contains("cap_parametervalue") ?


SMHviews.Entities[i]["cap_parametervalue"].ToString() : string.Empty;

allergyViews = allergy.Split(',');

else if (parameterName == "Entity Views - Condition")

string condition = SMHviews.Entities[i].Contains("cap_parametervalue") ?


SMHviews.Entities[i]["cap_parametervalue"].ToString() : string.Empty;

conditionViews = condition.Split(',');

else if (parameterName == "Entity Views - Family History")

{
string familyHistory =
SMHviews.Entities[i].Contains("cap_parametervalue") ? SMHviews.Entities[i]
["cap_parametervalue"].ToString() : string.Empty;

familyHistoryViews = familyHistory.Split(',');

else if (parameterName == "Entity Views - Smoking, Alcohol & Other")

string sao = SMHviews.Entities[i].Contains("cap_parametervalue") ?


SMHviews.Entities[i]["cap_parametervalue"].ToString() : string.Empty;

SAOViews = sao.Split(',');

alcoholViews = SAOViews.Where((s, j) => j % 2 == 0)

.Zip(SAOViews.Where((s, j) => j % 2 == 1), (a, b) => a + ", " + b)

.ToArray();

else if (parameterName == "Entity Views - Social Activity")

string social = SMHviews.Entities[i].Contains("cap_parametervalue") ?


SMHviews.Entities[i]["cap_parametervalue"].ToString() : string.Empty;

socialActivityViews = social.Split(',');

RetrieveEntityRequest retrieveTreatmentRequest = new RetrieveEntityRequest

EntityFilters = EntityFilters.Entity,

LogicalName = "cap_treatment"

};

RetrieveEntityResponse retrieveTreatmentEntityResponse =
(RetrieveEntityResponse)service.Execute(retrieveTreatmentRequest);

EntityMetadata treatmentEntity =
retrieveTreatmentEntityResponse.EntityMetadata;

int treatmentEntityTypeCode = (int)treatmentEntity.ObjectTypeCode;

if (returnedtypecode == treatmentEntityTypeCode)
{

if (treatmentViews.Length > 0)

ConditionExpression treatmentCondition = null;

treatmentCondition = new ConditionExpression("name",


ConditionOperator.In, treatmentViews);

query.Criteria.Conditions.Add(treatmentCondition);

RetrieveEntityRequest retrieveAllergyRequest = new RetrieveEntityRequest

EntityFilters = EntityFilters.Entity,

LogicalName = "cap_allergy"

};

RetrieveEntityResponse retrieveAllergyEntityResponse =
(RetrieveEntityResponse)service.Execute(retrieveAllergyRequest);

EntityMetadata allergyEntity = retrieveAllergyEntityResponse.EntityMetadata;

int allergyEntityTypeCode = (int)allergyEntity.ObjectTypeCode;

tracer.Trace("Allergy Code : " + allergyEntityTypeCode);

if (returnedtypecode == allergyEntityTypeCode)

if (allergyViews.Length > 0)

tracer.Trace("Allergy Count : " + allergyViews.Length);

ConditionExpression allergyCondition = null;

allergyCondition = new ConditionExpression("name", ConditionOperator.In,


allergyViews);

query.Criteria.Conditions.Add(allergyCondition);

}
RetrieveEntityRequest retrieveConditionRequest = new RetrieveEntityRequest

EntityFilters = EntityFilters.Entity,

LogicalName = "cap_condition"

};

RetrieveEntityResponse retrieveConditionEntityResponse =
(RetrieveEntityResponse)service.Execute(retrieveConditionRequest);

EntityMetadata conditionEntity =
retrieveConditionEntityResponse.EntityMetadata;

int conditionEntityTypeCode = (int)conditionEntity.ObjectTypeCode;

if (returnedtypecode == conditionEntityTypeCode)

if (conditionViews.Length > 0)

ConditionExpression condition = null;

condition = new ConditionExpression("name", ConditionOperator.In,


conditionViews);

query.Criteria.Conditions.Add(condition);

RetrieveEntityRequest retrieveFamilyHistoryRequest = new


RetrieveEntityRequest

EntityFilters = EntityFilters.Entity,

LogicalName = "cap_familyhistoryshort"

};

RetrieveEntityResponse retrieveFamilyHistoryEntityResponse =
(RetrieveEntityResponse)service.Execute(retrieveFamilyHistoryRequest);

EntityMetadata familyHistoryEntity =
retrieveFamilyHistoryEntityResponse.EntityMetadata;

int familyHistoryEntityTypeCode = (int)familyHistoryEntity.ObjectTypeCode;


if (returnedtypecode == familyHistoryEntityTypeCode)

if (familyHistoryViews.Length > 0)

ConditionExpression familyHistoryCondition = null;

familyHistoryCondition = new ConditionExpression("name",


ConditionOperator.In, familyHistoryViews);

query.Criteria.Conditions.Add(familyHistoryCondition);

RetrieveEntityRequest retrieveSAORequest = new RetrieveEntityRequest

EntityFilters = EntityFilters.Entity,

LogicalName = "cap_recreationaldruguse"

};

RetrieveEntityResponse retrieveSAOEntityResponse =
(RetrieveEntityResponse)service.Execute(retrieveSAORequest);

EntityMetadata SAOEntity = retrieveSAOEntityResponse.EntityMetadata;

int SAOEntityTypeCode = (int)SAOEntity.ObjectTypeCode;

if (returnedtypecode == SAOEntityTypeCode)

if (SAOViews.Length > 0)

ConditionExpression SAOCondition = null;

SAOCondition = new ConditionExpression("name", ConditionOperator.In,


alcoholViews);

query.Criteria.Conditions.Add(SAOCondition);

}
RetrieveEntityRequest retrieveSocialActivityRequest = new
RetrieveEntityRequest

EntityFilters = EntityFilters.Entity,

LogicalName = "cap_socialactivity"

};

RetrieveEntityResponse retrieveSocialActivityEntityResponse =
(RetrieveEntityResponse)service.Execute(retrieveSocialActivityRequest);

EntityMetadata socialActivityEntity =
retrieveSocialActivityEntityResponse.EntityMetadata;

int socialActivityEntityTypeCode = (int)socialActivityEntity.ObjectTypeCode;

if (returnedtypecode == socialActivityEntityTypeCode)

if (socialActivityViews.Length > 0)

ConditionExpression socialActivityCondition = null;

socialActivityCondition = new ConditionExpression("name",


ConditionOperator.In, socialActivityViews);

query.Criteria.Conditions.Add(socialActivityCondition);

RetrieveEntityRequest retrieveEntityRequest1 = new RetrieveEntityRequest

EntityFilters = EntityFilters.Entity,

LogicalName = "cap_careadvicegiven"

};

RetrieveEntityResponse retrieveAccountEntityResponse1 =
(RetrieveEntityResponse)service.Execute(retrieveEntityRequest1);

EntityMetadata regradeEntity = retrieveAccountEntityResponse1.EntityMetadata;

int regradeEntityTypeCode = (int)regradeEntity.ObjectTypeCode;


if (returnedtypecode == regradeEntityTypeCode)

string[] regradeViews = { "Authorised", "Not Authorised", "Pending


Authorisations" };

ConditionExpression regradeQueryCondition = null;

regradeQueryCondition = new ConditionExpression("name",


ConditionOperator.In, regradeViews);

query.Criteria.Conditions.Add(regradeQueryCondition);

catch (Exception ex)

tracer.Trace("An error occured in ShowHideQueueItemViewsBasedOnBU plugin exception


message: " + ex.Message);

public static List<BUAndViewsMapping> ReadUnsecuredConfigStringToObject(string json)

List<BUAndViewsMapping> deserializedBuAndViews = new List<BUAndViewsMapping>();

var ms = new MemoryStream(Encoding.UTF8.GetBytes(json));

var ser = new DataContractJsonSerializer(deserializedBuAndViews.GetType());

deserializedBuAndViews = ser.ReadObject(ms) as List<BUAndViewsMapping>;

ms.Close();

return deserializedBuAndViews;

EntityReference FetchRecord(IOrganizationService service, ITracingService tracingService)

{
EntityReference user = new EntityReference();

try

QueryExpression ApplicationParameterQuery = new


QueryExpression("cap_applicationparameter");

FilterExpression APfilterexpression = new FilterExpression(LogicalOperator.And);

ConditionExpression Apconditionexpression = new


ConditionExpression("cap_parametername", ConditionOperator.Equal, "adminuser");

APfilterexpression.AddCondition(Apconditionexpression);

ApplicationParameterQuery.ColumnSet = new ColumnSet("cap_parametervalue");

ApplicationParameterQuery.Criteria.Filters.Add(APfilterexpression);

EntityCollection APdata = service.RetrieveMultiple(ApplicationParameterQuery);

tracingService.Trace("Application Parameter Entity Count:" + APdata.Entities.Count);

if (APdata.Entities.Count > 0)

QueryExpression qe = new QueryExpression("systemuser");

FilterExpression fe = new FilterExpression(LogicalOperator.And);

string userName = APdata[0].Contains("cap_parametervalue") && APdata[0]


["cap_parametervalue"].ToString() != string.Empty ? APdata[0]["cap_parametervalue"].ToString() :
"";

ConditionExpression ce = new ConditionExpression("domainname",


ConditionOperator.Like, "%" + userName + "%");

fe.AddCondition(ce);

qe.ColumnSet = new ColumnSet("systemuserid", "fullname", "domainname");

qe.Criteria.Filters.Add(fe);

EntityCollection ec = service.RetrieveMultiple(qe);

tracingService.Trace("Entity Count:" + ec.Entities.Count);

if (ec.Entities != null && ec.Entities.Count > 0)

user.Id = ec.Entities[0].Id;

user.LogicalName = ec.Entities[0].LogicalName;
}

catch (Exception ex)

throw new InvalidPluginExecutionException("Error in FetchRecord function" +


Environment.NewLine + ex.Message);

return user;

public EntityCollection FetchApplicationParameter(IOrganizationService service, ITracingService


tracer)

try

string FetchApplicationParameter = @"<fetch version='1.0' output-format='xml-platform'


mapping='logical' distinct='false'>

<entity name='cap_applicationparameter'>

<attribute name='cap_applicationparameterid' />

<attribute name='cap_parametername' />

<attribute name='cap_parametervalue' />

<order attribute='cap_parametername' descending='false' />

<filter type='and'>

<condition attribute='cap_parametername' operator='not-null' />

<condition attribute='statecode' operator='eq' value='0' />

</filter>

</entity>

</fetch>";
EntityCollection ResultApplicationParameter = service.RetrieveMultiple(new
FetchExpression(FetchApplicationParameter));

if (ResultApplicationParameter != null && ResultApplicationParameter.Entities.Count > 0)

return ResultApplicationParameter;

catch (Exception ex)

tracer.Trace("An error occurred in the function FetchApplicationParameter of public class


ShowHideQueueItemViewsBasedOnBU Plug -in." + Environment.NewLine + ex);

throw;

return null;

public class BUAndViewsMapping

public string BUName { get; set; }

public List<string> Views { get; set; }

Sample Json Format for above plugin :


[

"BUName": "Sales",

"Views": [

"Sales View 1",


"Sales View 2",

"Sales View 3"

},

"BUName": "Support",

"Views": [

"Support View 1",

"Support View 2"

},

"BUName": "Marketing",

"Views": [

"Marketing View 1",

"Marketing View 2",

"Marketing View 3"

},

"BUName": "HR",

"Views": [

"HR View 1",

"HR View 2"

Using Shared Variables


Shared variables allow data to be passed between plugins and other components during a single

transaction.

1. Setting Shared Variables:


o Use the SharedVariables property of the plugin execution context to store data.

context.SharedVariables["key"] = value;

2. Retrieving Shared Variables:

o Access shared variables in subsequent plugins or custom workflow activities.

var value = context.SharedVariables["key"];

Example Plugin for Shared Variables :


using System;
using Microsoft.Xrm.Sdk;

public class AccountPlugin : IPlugin


{
public void Execute(IServiceProvider serviceProvider)
{
// Get the execution context from the service provider.
IPluginExecutionContext context =
(IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

// Get the service factory.


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

// Get the organization service.


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

// Check if this is an 'Update' message and if the entity is an 'Account'


if (context.MessageName.ToLower() == "update" &&
context.PrimaryEntityName.ToLower() == "account")
{
Entity targetEntity = (Entity)context.InputParameters["Target"];
bool isSpecialAccount = targetEntity.Contains("name") &&
targetEntity["name"].ToString() == "Special Account";
// Set shared variable to indicate whether the condition is met
context.SharedVariables["IsSpecialAccount"] = isSpecialAccount;
if (isSpecialAccount)
{
if (targetEntity.Contains("new_specialfield"))
{
targetEntity["new_specialfield"] = "Updated due to Special Account";
service.Update(targetEntity);
}
}
}
// Later in the plugin, in a different step, we can check for the shared variable.
if (context.SharedVariables.Contains("IsSpecialAccount"))
{
bool isSpecialAccount = (bool)context.SharedVariables["IsSpecialAccount"];
if (isSpecialAccount)
{
Console.WriteLine("This is a Special Account, proceed with further actions.");
}
}
}
}

Context in Plugins
The context in a plugin refers to the IPluginExecutionContext object, which contains
information about the runtime environment of the plugin. It provides detailed information
about the event that triggered the plugin, the data being processed, and other relevant
parameters.
Key properties of the context include:
 MessageName: The message (operation) that triggered the plugin, e.g., Create,
Update, Delete, Assign, SetState, etc.
 PrimaryEntityName: The name of the entity being acted upon (e.g., account,
contact, opportunity).
 PrimaryEntityId: The ID of the entity being acted upon. This is typically the unique
identifier (GUID) of the record.
 InputParameters: A collection of parameters that are passed into the plugin, which
can include data about the entity being modified or other relevant information.
 OutputParameters: Parameters that the plugin can use to modify the outcome of
the operation.
 Depth: The execution depth (used to prevent infinite recursion in workflows or
plugins).
 UserId: The GUID of the user who triggered the plugin.
 Stage: Indicates the stage at which the plugin is executed (pre-operation, post-
operation).
 SecurityContext: Information about the security privileges of the user executing the
plugin.
For example, in a plugin, you can check the MessageName to ensure that your logic only
runs for a certain message, or use the PrimaryEntityId to fetch additional data related to the
entity being worked on.

Target in Plugins
The target in a plugin refers to the Target parameter passed into the plugin, which typically
contains the entity object that the operation is being performed on. This is usually available
in the InputParameters collection.
The target could be:
 For Create: The entity record that is being created.
 For Update: The entity record that is being updated, containing the updated fields.
 For Delete: The entity record that is being deleted (though you typically only get the
ID here and not the full entity data).
 For Associate/Disassociate: The related entity data.
You can access the target by using the InputParameters collection in the context. For
example, in an update operation, you can retrieve the modified entity from the Target
property to determine what fields have changed.
Example of how you access the target:
public void Execute(IServiceProvider serviceProvider)
{
// Retrieve the plugin execution context
IPluginExecutionContext context =
(IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

// Retrieve the target entity (for Create or Update)


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

if (targetEntity != null)
{
// Work with the target entity (e.g., update fields)
Guid entityId = targetEntity.Id;
// You can also access specific attributes of the target entity like:
string name = targetEntity["name"].ToString();
}
}

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy