Pillaro.Dataverse.PluginFramework
1.2.2
Prefix Reserved
dotnet add package Pillaro.Dataverse.PluginFramework --version 1.2.2
NuGet\Install-Package Pillaro.Dataverse.PluginFramework -Version 1.2.2
<PackageReference Include="Pillaro.Dataverse.PluginFramework" Version="1.2.2" />
<PackageVersion Include="Pillaro.Dataverse.PluginFramework" Version="1.2.2" />
<PackageReference Include="Pillaro.Dataverse.PluginFramework" />
paket add Pillaro.Dataverse.PluginFramework --version 1.2.2
#r "nuget: Pillaro.Dataverse.PluginFramework, 1.2.2"
#:package Pillaro.Dataverse.PluginFramework@1.2.2
#addin nuget:?package=Pillaro.Dataverse.PluginFramework&version=1.2.2
#tool nuget:?package=Pillaro.Dataverse.PluginFramework&version=1.2.2
Pillaro Dataverse Plugin Framework
A task-based framework for building predictable and testable Microsoft Dataverse plugins in C#.
What this package provides
- A small, opinionated runtime for Dataverse plugin development based on tasks (
Task= single responsibility). - A fluent validation pipeline that strictly separates validation from execution.
- Deterministic execution model — a task either clearly runs or clearly does not run.
- Validation-level logging — each validation rule produces a clear log message explaining why the task did or did not execute.
- Structured logging and conventions suitable for diagnostics and automated testing.
- Opinionated helpers for common scenarios (e.g. autonumbering, entity images, deterministic execution patterns).
- Generated local tooling for early-bound entity generation through Power Platform CLI (
pac modelbuilder).
Why use it
- Reduce complexity — replace large plugin classes with focused, isolated tasks.
- Improve testability — each task is independently testable and deterministic.
- Enforce consistency — shared patterns across teams reduce onboarding time and bugs.
- Make behavior predictable — no hidden execution paths or implicit logic.
- Designed for long-term maintainability — clear task pipeline, enforced project structure and programmatic testing support reduce complexity and cost of future changes.
Platform constraints (important)
This framework is designed specifically for Microsoft Dataverse plugin runtime:
- Only
.NET Framework 4.6.2is supported by the platform - Plugin must be deployed as a single assembly (DLL)
- All dependencies must be merged (ILMerge or equivalent)
- Assemblies should be strong-name signed
These constraints are reflected in the framework design.
Logging (recommended)
The framework includes structured logging at the task and validation level.
Plugins work without any additional setup, however it is strongly recommended to install the Pillaro Framework application into your Dataverse environment.
This application allows you to:
- view logs from individual task executions
- understand why a task was skipped or executed
- troubleshoot issues without debugging the plugin directly
The application can be found in the project repository under the power-platform-solutions/framework folder.
To enable logging, configure the following setting in Dataverse:
- In the Runtime Setting entity, set
MinimalSeverityLevelto0or1to enable full debug-level framework logging.
MinimalSeverityLevel is a minimum severity threshold. 0 or 1 saves all severities, 2 saves Info and higher, 3 saves Warning and Error, and 4 saves Error only.
For production environments, 3 is the recommended default. Full logging (0 or 1) should be enabled only temporarily when detailed diagnostics are required.
Quick start
- Install the package via NuGet:
Install-Package Pillaro.Dataverse.PluginFramework
- Create a solution-level
PluginBase(one per solution, used as a common entry point and configuration root):
public class PluginBase : PluginFramework.Plugins.PluginBase
{
public PluginBase(string unsecureConfig, string secureConfig)
: base(unsecureConfig, secureConfig)
{
}
public override string GetVersion() => "1.0";
}
- Create a plugin class and register tasks (one plugin per logical area or entity):
public class ContactPlugin : PluginBase
{
public ContactPlugin(string unsecureConfig, string secureConfig) : base(unsecureConfig, secureConfig)
{
RegisterTask<ValidateContactTask>(
PluginStage.Preoperation,
new[] { "Create", "Update" },
"contact",
PluginMode.Synchronous);
}
}
- Implement a
Task(all business logic belongs here):
public class ValidateContactTask : TaskBase<Logic.Contact>
{
public ValidateContactTask(IServiceProvider services, TaskContext ctx)
: base(services, ctx) { }
protected override ICompleteValidation AddValidations(IBasicModeValidation validator)
{
return validator
.WithMode(PluginMode.Synchronous)
.WithStage(PluginStage.Preoperation)
.WithMessages(new[] { "Create", "Update" })
.ForEntity(ContextEntity.LogicalName);
}
protected override void DoExecute()
{
// Business logic only
}
}
- Enable assembly signing using a strong-name key file:
key.snk
The key file should be placed in the plugin project root and used during build and merge.
- Configure post-build action for assembly merge.
Post-build actions are generated after rebuild and are available in:
Tools/ILMerge/
Use the variant that matches your project structure:
PostBuildAction-logic_plugin-projects.txt
Use this when your solution contains separate Logic and Plugin projects.
This variant merges the plugin assembly together with the Logic assembly.PostBuildAction-single-project.txt
Use this when all logic is implemented in a single plugin project.
This variant merges only the plugin assembly and its dependencies.
These scripts run Tools\ILMerge\ILMerge.exe from the project-local tools folder and derive paths from $(MSBuildProjectDirectory), $(Configuration), and $(AssemblyName).
They do not use $(TargetDir), $(TargetFileName), or $(ProjectDir).
If you are using the generated Visual Studio template, the Logic + Plugins variant can use:
set "LOGIC_DLL=$ext_safeprojectname$.Logic.dll"
- Build the plugin project.
After signing and post-build configuration, the project produces a single merged assembly ready for deployment. The package also generates ILMerge tooling in Tools/ILMerge/, deployment helpers in Tools/Deployment/, early-bound generation helpers in Tools/EarlyBound/, and a PillaroSettings.json file in the plugin project root.
- Optional: generate early-bound entity classes.
The package generates early-bound helpers after rebuild:
Tools/EarlyBound/
Configure Tools/EarlyBound/EarlyBoundSettings.json, authenticate with Power Platform CLI, and run:
Tools\EarlyBound\GenerateEarlyBound.bat
Generated C# files are written to EarlyBound/ in the project root.
- Deploy the plugin assembly.
Recommended tools:
- Plugin Registration Tool
- generated
Tools/Deployment/DeployPlugins.batorTools/Deployment/DeployPlugins.ps1
Core concepts
Plugin
Entry point registered in Dataverse. Matches incoming event to registered tasks.Task
Single unit of work with two explicit phases:- Validation — defines when the task should run
- Execution — pure business logic
Validation model
Designed to guarantee deterministic execution — a task either clearly runs or clearly does not run.
Each validation rule logs a message explaining its decision, making it easy to understand why a task was skipped or executed.
This significantly improves debugging, observability and automated testing.
Requirements & packaging notes
- Target runtime:
.NET Framework 4.6.2 - Dependencies:
Microsoft.CrmSdk.CoreAssemblies,Newtonsoft.Json - Plugin must be deployed as a single merged assembly (ILMerge or equivalent)
- Strong-name signing is recommended for all assemblies
Where to find more
License
This project is licensed under the Apache License, Version 2.0. See the LICENSE file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Framework | net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
-
.NETFramework 4.6.2
- Microsoft.CrmSdk.CoreAssemblies (>= 9.0.2.60)
- Newtonsoft.Json (>= 13.0.4)
-
net8.0
- Microsoft.PowerPlatform.Dataverse.Client (>= 1.2.10)
- Newtonsoft.Json (>= 13.0.4)
- System.Runtime.Caching (>= 8.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Pillaro.Dataverse.PluginFramework:
| Package | Downloads |
|---|---|
|
Pillaro.Dataverse.PluginFramework.Testing
Integration testing library for Microsoft Dataverse (Dynamics 365) plug-ins built with the Pillaro framework. Runs xUnit v3 tests against a real environment, prepares test data through repositories and automatically cleans up everything a test creates. Apache-2.0 licensed, free for commercial use. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.2.2 | 48 | 9/12/2026 |
| 1.2.0 | 73 | 9/9/2026 |
| 1.2.0-rc.569 | 72 | 9/6/2026 |
| 1.2.0-rc.559 | 65 | 9/6/2026 |
| 1.1.3-rc.550 | 72 | 9/5/2026 |
| 1.1.3-rc.542 | 70 | 9/4/2026 |
| 1.1.2 | 111 | 8/31/2026 |