-
Notifications
You must be signed in to change notification settings - Fork 2
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.)

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);
// ...
}
}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.
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 Locally —
dotnet buildthe plugin project. - Build Package & Deploy — builds and deploys the plugin as a plugin package to your environment.
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.
}
}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.