Writing a Plugin - rezanid/xrmtools GitHub Wiki

Creating a new plugin with Xrm Tools is straightforward and requires minimal work to setup. Xrm Tools lets you define your entire plugin—including when it should run and what data it needs—directly in code, so you avoid switching between the code editor, Plugin Registration Tool, and web UI.

Prerequisites

Ensure you've completed the Getting Started; as a reminder:

  1. Set the Current Environment in Visual Studio.

  2. Use PackageReference instead of packages.json.

    If you see packages.json under your project tree, right-click on it → Migrate packages.config to PackageReference...

  3. The following NuGet packages are installed.

Note

Refer to Migrate from packages.config to PackageReference for more details.

Creating the Plugin Class

1. Add a Class and Annotate it

  • Create a new class:right-click your project in Solution Explorer → Add > Class…

  • Name it clearly (e.g., ContactUpdatePlugin.cs).

  • Make the class partial and inherit from IPlugin.

  • Give it a meaningful name that includes “Plugin” (this is recommended for clarity – e.g., AccountUpdatePlugin.cs or ContactUpdatePlugin.cs).

  • Make the class partial and inherit from IPlugin.

  • Add the [Plugin] attribute:

using Microsoft.Xrm.Sdk;
using XrmTools.Meta.Attributes;

[Plugin]
public partial class ContactUpdatePlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        // To be implemented
        throw new InvalidPluginExecutionException("Execute not implemented");
    }
}
  • Optionally, specify properties like Description in [Plugin].

2. Define Steps

Use [Step] to specify when the plugin runs, on which entity and other required details:

[Plugin]
[Step("Update", "contact", "firstname,lastname,description", Stages.PreOperation, ExecutionMode.Synchronous)]
public partial class ContactUpdatePlugin : IPlugin { ... }
  • Message: Operation ("Update")
  • Entity: Target entity ("contact")
  • Filtering Attributes: Optional, specifies fields triggering the plugin.
  • Stage: At which stage in the execution pipeline your plugin executes (Stages.PreOperation )
  • ExecutionMode: Synchronous vs Asynchronous.

3. Images (Optional)

Add [Image] immediately after [Step] to get Pre/Post Images for that step:

[Plugin]
[Step("Update", "contact", "firstname,lastname,description", Stages.PreOperation, ExecutionMode.Synchronous)]
[Image(ImageTypes.PostImage, "firstname,lastname,description")]
public partial class ContactUpdatePlugin : IPlugin { ... }

4. Implement Execute

Initially, add minimal logic. Detailed implementation follows after enabling code generation (Enabling Code Generation):

public void Execute(IServiceProvider serviceProvider)
{
    throw new InvalidPluginExecutionException("Execute not implemented");
}

Enhanced IntelliSense

While you have been typing in the editor of Visual Studio, you might have noticed that, Xrm Tools enhances IntelliSense:

  • Suggests valid message/entity names.
  • Lists fields for filtering attributes clearly along with helpful metadata.
attribute auto-completion screenshot attribute auto-completion screenshot

Visual Studio IntelliSense showing Xrm Tools helping with Step attribute parameters. In this example, after selecting the Create message, IntelliSense suggests entity names like contact and others, filtered to those relevant to a Create. Notice the icons at the bottom for filtering entity types (Standard, Activity, Virtual, Elastic); you can toggle these or use keyboard shortcuts* (Alt + S, Alt + A, Alt + V, Alt + E) to narrow the suggestions. Similarly, when adding filtering attributes, the suggested attribute names will be listed and visually distinguished, making it easy to pick the right ones. Keep in mind adding filtering attributes to a Create message is not useful.

Screenshot of Intellisense in Visual Studio for filtering attributes

Enabling Code Generation

You can also enable code generation for your plugins, further enhancing plugin development experience and saving time. Learn how to enable plugin code generation next.

Read Next:

⚠️ **GitHub.com Fallback** ⚠️