Microsoft Dynamics CRM Plugins Tutorial (C# for Beginners)

Microsoft Dynamics CRM Plugins Tutorial (C# for Beginners)

Plugins are small C# classes that run automatically when something happens in Dynamics CRM (for example, when a record is created or updated). Each plugin class implements the interface and must have an method. This method is called by CRM when the plugin is triggered. The parameter is a toolbox we use to get useful objects like the execution context, organization service, or tracing service.

Below are several simple plugin examples. For each example we explain what the plugin does, when it runs, what event triggers it, and then show the complete C# code. After each code sample, we explain every line in beginner-friendly language.


  1. Plugin Example: Set Default Description on Account Create (Pre-Operation)

What it does: When a new Account is being created, this plugin sets its Description field to a default message.

When it runs: This is a Pre-Operation plugin (stage PreOperation). It runs before the account is saved to the database, so we can modify the record before it is stored.

Triggers on: The Create message of the account entity (i.e., when an account record is created).

using System;

using Microsoft.Xrm.Sdk;

public class AccountCreatePrePlugin : IPlugin

{

public void Execute(IServiceProvider serviceProvider)

{

// Get the execution context service

IPluginExecutionContext context =

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

// Check that the input parameters contain a Target entity

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

{

// Obtain the account entity from the input parameters

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

// Make sure this is really an Account record

if (account.LogicalName == "account")

{

// Set the Description field of the account

account["description"] = "This account is newly created.";

}

}

}

}

and – These lines import the namespaces that contain CRM plugin classes and interfaces. We need to use , , and .

– This defines a new plugin class called that implements the interface. This interface requires an method, which is where our code will run.

– This is the main method that CRM calls when the plugin runs. The parameter is provided by CRM and lets us get other services (like the execution context).

– We ask the for the execution context. The context (`IPluginExecutionContext`) contains information about the current event (like which record triggered it, which message – Create in this case – and which stage).

– CRM passes the data for the operation in the . For a Create event, the new record is under the parameter. We check if exists and is an (a record). This ensures we have an entity to work with.

– We cast the parameter to an object and store it in . This variable now represents the new Account record.

– We double-check that the entity’s logical name is (in case this plugin was accidentally registered for another entity). This makes sure we are working with an Account record.

– We set the Description field of the account to a specific string. Since this is a Pre-Operation plugin, modifying the entity here means the new value will be saved to the database when the create operation completes.

2. Plugin Example: Create Follow-up Task on Account Create (Post-Operation)

What it does: After a new Account is created, this plugin automatically creates a new Task record to remind someone to follow up with the account.

When it runs: This is a Post-Operation plugin (stage PostOperation). It runs after the account has been saved to the database, so now the account ID exists and we can reference it.

Triggers on: The Create message of the account entity.

using System;

using Microsoft.Xrm.Sdk;

public class AccountCreatePostPlugin : IPlugin

{

public void Execute(IServiceProvider serviceProvider)

{

// Get the execution context and organization service

IPluginExecutionContext context =

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

IOrganizationServiceFactory serviceFactory =

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

IOrganizationService service =

serviceFactory.CreateOrganizationService(context.UserId);

// Only proceed if the Target is an Account entity

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

{

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

if (account.LogicalName == "account")

{

// Create a new Task entity to follow up

Entity task = new Entity("task");

task["subject"] = "Follow up with new account";

task["description"] = "Call or email the new account.";

// Link the task to the account that was just created

if (context.OutputParameters.Contains("id"))

{

Guid accountId = new Guid(context.OutputParameters["id"].ToString());

task["regardingobjectid"] = new EntityReference("account", accountId);

}

// Create the task in CRM

service.Create(task);

}

}

}

}

and – Here we get the organization service which allows us to create, update, or delete records in CRM. We first get a from the provider, then call to get the . The ensures actions run with the same user privileges as the triggering user.

We again retrieve the context and check the just like in the first example, to get the entity.

– We create a new Task entity in code. The constructor takes the entity logical name .

– We set the Subject field of the task.

– We set the Description field of the task.

– In a Create message, CRM puts the newly created record’s ID into . We retrieve that ID and set the task’s regardingobjectid (a lookup field) to reference the new account. This links the task to the account.

– Finally, we call on the service to save the new Task record in CRM. This actually creates the follow-up task in the database.

Plugin Example: Update Contact’s First Name to Uppercase (Pre-Operation)

What it does: Whenever a Contact record is updated, this plugin checks if the first name changed and, if so, makes the first name all uppercase letters.

When it runs: Pre-Operation (before saving the update) on the Update message.

Triggers on: The Update message of the contact entity.

using System;

using Microsoft.Xrm.Sdk;

public class ContactUpdatePlugin : IPlugin

{

public void Execute(IServiceProvider serviceProvider)

{

// Get context

IPluginExecutionContext context =

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

// Only proceed if the Target is a Contact entity

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

{

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

if (contact.LogicalName == "contact")

{

// If First Name is in the changed fields

if (contact.Contains("firstname"))

{

string firstname = contact["firstname"].ToString();

contact["firstname"] = firstname.ToUpper();

}

}

}

}

}

We retrieve the context as before and check that is an entity.

– Casts the target to an , representing the contact being updated.

– Verifies this is a Contact record.

– Checks if the firstname field is present in the update. This means the user changed the first name.

– Reads the current first name into a C# string.

– Converts the string to all uppercase and writes it back to the entity. Because this is a Pre-Operation plugin, the uppercase name will be saved when the update completes.

3. Plugin Example: Validate Contact Email (Pre-Operation)

What it does: When a Contact is created or updated, this plugin ensures the Email field contains an “@” symbol. If not, it throws an error to stop the save.

When it runs: Pre-Operation on Create or Update (so the validation happens before saving).

Triggers on: The Create and Update messages of the contact entity (you would register the same plugin for both events).

using System;

using Microsoft.Xrm.Sdk;

public class ContactEmailValidationPlugin : IPlugin

{

public void Execute(IServiceProvider serviceProvider)

{

// Get context

IPluginExecutionContext context =

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

// Only proceed if the Target is a Contact entity

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

{

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

if (contact.LogicalName == "contact")

{

// If Email address is provided

if (contact.Contains("emailaddress1"))

{

string email = contact["emailaddress1"].ToString();

// Check for '@' character

if (!email.Contains("@"))

{

// Throw exception to cancel the operation

throw new InvalidPluginExecutionException("Email address is invalid. It must contain '@'.");

}

}

}

}

}

}

We get the context and target entity as before.

We check to see if the Email field was set or changed.

– Reads the email value.

– If the email does not contain an “@”, we throw an . Throwing this exception in a synchronous plugin stops the save operation and shows the error message to the user. In simple terms, this prevents the contact from being saved with an invalid email.

Plugin Example: Prevent Account Deletion (Pre-Operation)

What it does: This plugin stops users from deleting an Account. It throws an error whenever a delete is attempted.

When it runs: Pre-Operation on the Delete message (before deletion).

Triggers on: The Delete message of the account entity.

using System;

using Microsoft.Xrm.Sdk;

public class AccountDeletePlugin : IPlugin

{

public void Execute(IServiceProvider serviceProvider)

{

// Get context

IPluginExecutionContext context =

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

// Only proceed if the Target is an Account reference

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

{

EntityReference accountRef = (EntityReference)context.InputParameters["Target"];

if (accountRef.LogicalName == "account")

{

// Throw exception to cancel deletion

throw new InvalidPluginExecutionException("Deleting accounts is not allowed.");

}

}

}

}

– For a Delete message, CRM passes an (which contains the ID of the record) instead of an . We check that is an .

– Casts the target to an .

– Ensures the reference is for an Account.

– This line throws an exception, which tells CRM to cancel the delete operation. The error message ("Deleting accounts is not allowed.") will be shown to the user. This prevents the account from being deleted.

Each of the above examples shows a complete plugin class with very simple logic. Every line of code has been explained in basic terms. In summary:

A plugin class implements and has .

Inside , we typically get the execution context via .

We check to access the record (`Entity`) or reference that triggered the event.

In Pre-Operation plugins, modifying the ’s fields directly updates what is saved.

In Post-Operation plugins, we often use (from ) to create or update other records.

Throwing an in a synchronous plugin cancels the operation (used for validation).

With these basics and examples, a beginner should be able to write simple Dynamics CRM plugins in C#, understand when they run (pre vs post), and know which events (create, update, delete) they respond to.

Mehul Dabhi

Software Engineer | Microsoft CRM & Power Platform | Power Automation | Power Apps | Model Driven Apps

1mo

👍

Like
Reply
Rakesh Kasangottu

CRM || Power Apps || Microsoft Power Automate || Power Pages || Power Portals || Modern Driven Apps || Canvas Application || Work flows

2mo

Definitely worth reading

Like
Reply
Amgad SalahEldin

Helping Businesses Improve Customer Experience with AI-Powered Cloud Contact Centers | Amazon Connect Specialist | Expert in CRM Integrations & Omni channel Solutions

3mo

Fantastic resource. At Odea Integrations, we guide newcomers through Dynamics CRM plugin development—simplifying concepts, accelerating learning, and supporting real-world implementation success.

To view or add a comment, sign in

Others also viewed

Explore topics