Skip to content

Plugins

pete-mc edited this page Jul 7, 2026 · 16 revisions

Plugins

The Plugins project type covers the full plugin and custom-workflow-activity lifecycle:

  • Create plugin and workflow classes.
  • Register steps with CodeLens decorations right in the C# file.
  • Generate early-bound types from your environment.
  • Build with the .NET SDK and deploy as a plugin package.
  • Unit test with DataverseUnitTest (MSTest, xUnit, or NUnit).

New plugin projects are created with pac plugin init, so they're SDK-style and build with dotnet on any OS. (Plugin assemblies target .NET Framework 4.6.2 — a Dataverse sandbox requirement — but dotnet build compiles that on Windows, macOS, and Linux.)

Plugin menu

Create Plugin / Workflow Class

Right-click the project folder and choose Create Plugin Class or Create Workflow Class, then enter a name. The .csproj includes all files in the folder, so no project edits are needed.

public class ClassName : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        var tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
        var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
        var service = factory.CreateOrganizationService(context.UserId);
        // ...
    }
}

Registering steps (CodeLens decorations)

Steps are registered from attributes on your class. Add or edit them with the CodeLens actions above each class in a C# file, or the Add Plugin/Workflow Decoration commands. A unique Id GUID is generated for you.

[CrmPluginRegistration(MessageNameEnum.Create, "contact", StageEnum.PostOperation,
  ExecutionModeEnum.Synchronous, "", "Create Contact step", 1, IsolationModeEnum.Sandbox,
  Id = "90705ddd-1442-4403-8cb6-48807e2ecaf7")]
public class ClassName : IPlugin { /* ... */ }

You'll be prompted for the message, table, stage, execution mode, filtering attributes, step name, order, and isolation mode.

Generate Early Bound

Use Generate Early Bound (or the Early Bound Options view) to generate strongly-typed classes for your tables and messages. The options tree — powered by pac modelbuilder — lets you:

  • Pick the tables and messages to generate.
  • Configure the namespace, output directory, service-context name, and other model-builder settings.

Refresh the available tables from Dataverse, add/remove them with the inline controls, then click Generate Early Bound.

Build & Deploy

  • Build Locallydotnet build the plugin project.
  • Build Package & Deploy — builds and deploys the plugin as a plugin package to your environment.

Unit testing

Click Setup Unit Testing to add a test project wired up with DataverseUnitTest. Choose your framework (MSTest, xUnit, or NUnit); the extension creates the project, references your plugin, installs the package, targets a compatible framework, and adds a boilerplate test.

  • Create Plugin Test — scaffolds a new test class.
  • Run Tests — runs dotnet test.
public class PluginTests
{
    [Fact]
    public void Example()
    {
        // Arrange a DataverseUnitTest context, execute the plugin, assert the result.
    }
}

Legacy projects

Plugin projects created before template version 3 used spkl and are deprecated. They still load, but new features target the modern pac/dotnet flow above — create a new plugin project to migrate.

Clone this wiki locally