Digitall.Plugins
2.0.0
dotnet add package Digitall.Plugins --version 2.0.0
NuGet\Install-Package Digitall.Plugins -Version 2.0.0
<PackageReference Include="Digitall.Plugins" Version="2.0.0" />
<PackageVersion Include="Digitall.Plugins" Version="2.0.0" />
<PackageReference Include="Digitall.Plugins" />
paket add Digitall.Plugins --version 2.0.0
#r "nuget: Digitall.Plugins, 2.0.0"
#:package Digitall.Plugins@2.0.0
#addin nuget:?package=Digitall.Plugins&version=2.0.0
#tool nuget:?package=Digitall.Plugins&version=2.0.0
Digitall.Plugins
NuGet package providing base classes and extensions to simplify Microsoft Dataverse plugin development with improved logging and error handling.
<p align="center"> <a href="LICENSE.md" target="_blank"> <img src="https://img.shields.io/github/license/DIGITALLNature/DigitallAssemblyPower.svg" alt="GitHub license"> </a> <a href="https://github.com/DIGITALLNature/DigitallAssemblyPower/releases" target="_blank"> <img src="https://img.shields.io/github/tag/DIGITALLNature/DigitallAssemblyPower.svg" alt="GitHub tag (latest SemVer)"> </a> <a href="https://www.nuget.org/packages/Digitall.Plugins" target="_blank"> <img src="https://img.shields.io/nuget/v/Digitall.Plugins" alt="NuGet"> </a> <a href="https://github.com/DIGITALLNature/DigitallAssemblyPower/graphs/contributors" target="_blank"> <img src="https://img.shields.io/github/contributors-anon/DIGITALLNature/DigitallAssemblyPower.svg" alt="GitHub contributors"> </a> </p>
Table of Contents
Installation
dotnet add package Digitall.Plugins
For a project in a subdirectory:
dotnet add src/MyProject package Digitall.Plugins
Quick Start
Choose the base class that best fits your plugin design:
Using PluginSkeleton (Recommended)
using Digitall.Plugins;
using Microsoft.Xrm.Sdk;
public class MyPlugin : PluginSkeleton
{
protected override void ExecuteInternal(IServiceProvider serviceProvider)
{
var context = serviceProvider.GetExecutionContext();
var entity = context.GetTarget<Entity>();
// Your plugin logic here
}
}
Using Executor
using Digitall.Plugins;
public class MyExecutor : Executor
{
protected override ExecutionResult Execute()
{
var entity = Entity; // Pre-unwrapped from context
var id = entity.Id;
return ExecutionResult.Ok;
}
}
Usage
PluginSkeleton
PluginSkeleton is a modern, structured base class with built-in logging and exception handling. It automatically logs execution start/end times, parameters, and errors.
Benefits:
- Automatic performance logging (elapsed milliseconds)
- Structured error logging with full context
- Support for Microsoft.Extensions.Logging.ILogger
- Support for Dataverse PluginTelemetry logging
- Automatic exception propagation with logging
Override abstract method:
protected abstract void ExecuteInternal(IServiceProvider serviceProvider);
Example:
using Digitall.Plugins;
using Digitall.Plugins.Extensions;
using Microsoft.Xrm.Sdk;
public class AccountPlugin : PluginSkeleton
{
protected override void ExecuteInternal(IServiceProvider serviceProvider)
{
var context = serviceProvider.GetExecutionContext();
var account = context.GetTarget<Entity>();
// Access services via extensions
var logger = serviceProvider.GetLogger();
var service = serviceProvider.GetOrganizationService();
logger.LogInformation("Processing account: {0}", account.Id);
}
}
Executor
Executor is a legacy-compatible base class that provides convenient property accessors for common plugin execution patterns. It implements the "stateless" Microsoft recommendation by cloning itself on each invocation.
Benefits:
- Simplified property access (Entity, EntityReference, PreEntityImage, etc.)
- Pre-configured OrganizationService properties (Secured/Elevated)
- Support for secure and unsecure configuration
- ExecutionResult tracking
- Support for CreateMultiple/UpdateMultiple operations
Constructor parameters (optional):
| Parameter | Type | Description |
|---|---|---|
unsecure |
string |
Unsecure configuration string |
secure |
string |
Secure configuration string |
Common Properties:
| Property | Type | Description |
|---|---|---|
Entity |
Entity |
The target entity for single-record operations |
GetEntities() |
EntityCollection |
Target entities for CreateMultiple/UpdateMultiple |
EntityReference |
EntityReference |
The target entity reference |
PreEntityImage |
Entity |
Pre-operation entity image |
GetPreEntityImages() |
EntityCollection |
Pre-operation entity images (for bulk operations) |
PostEntityImage |
Entity |
Post-operation entity image |
GetPostEntityImages() |
EntityCollection |
Post-operation entity images (for bulk operations) |
SecuredOrganizationService |
IOrganizationService |
Organization service with caller's privileges |
ElevatedOrganizationService |
IOrganizationService |
Organization service with system privileges |
Core |
IPluginExecutionContext |
The raw execution context |
Example:
using Digitall.Plugins;
public class AccountExecutor : Executor
{
protected override ExecutionResult Execute()
{
var entity = Entity;
var accountName = entity.GetAttributeValue<string>("name");
// Use pre-configured services
var service = SecuredOrganizationService;
return ExecutionResult.Ok;
}
}
Service Provider Extensions
Access Dataverse services and utilities through extension methods on IServiceProvider.
using Digitall.Plugins.Extensions;
using Microsoft.Xrm.Sdk;
var context = serviceProvider.GetExecutionContext();
var service = serviceProvider.GetOrganizationService();
var elevated = serviceProvider.GetElevatedOrganizationService();
var logger = serviceProvider.GetLogger();
var tracing = serviceProvider.GetTracingService();
var timeProvider = serviceProvider.GetTimeProvider();
var miService = serviceProvider.GetManagedIdentityService();
Available Methods:
| Method | Returns | Description |
|---|---|---|
GetExecutionContext() |
IPluginExecutionContext7 |
The plugin execution context |
GetOrganizationService() |
IOrganizationService |
Service for current user (from context) |
GetOrganizationService(Guid userId) |
IOrganizationService |
Service for specified user |
GetElevatedOrganizationService() |
IOrganizationService |
Service with system (elevated) privileges |
GetTracingService() |
ITracingService |
Tracing service for legacy logging |
GetLogger() |
ILogger |
Default Dataverse logger (combined Telemetry + Tracing) |
GetLogger(params LogSink[] sinks) |
ILogger |
Logger targeting specific sinks |
GetTimeProvider() |
TimeProvider |
Current time provider (testable) |
GetManagedIdentityService() |
IManagedIdentityService |
Managed identity service for token acquisition |
Logging
The library provides integrated logging through ILogger (Microsoft.Extensions.Logging compatible):
var logger = serviceProvider.GetLogger();
logger.LogInformation("Processing entity {0}", entityId);
logger.LogWarning("Warning: {0}", message);
logger.LogError("Error occurred: {0}", exception);
Log Sinks:
By default, logs go to both PluginTelemetry and TracingService:
// Logs to TracingService only
var logger1 = serviceProvider.GetLogger(ServiceProviderExtensions.LogSink.TracingService);
// Logs to PluginTelemetry only
var logger2 = serviceProvider.GetLogger(ServiceProviderExtensions.LogSink.PluginTelemetry);
// Logs to both (default)
var logger3 = serviceProvider.GetLogger(
ServiceProviderExtensions.LogSink.PluginTelemetry,
ServiceProviderExtensions.LogSink.TracingService
);
Plugin Execution Context Extensions
Simplified access to execution context data with type-safe casting:
using Digitall.Plugins.Extensions;
var context = serviceProvider.GetExecutionContext();
// Type-safe entity retrieval
var account = context.GetTarget<Account>();
var accounts = context.GetTargets<Account>(); // For bulk operations
// Image retrieval with casting
var preImage = context.GetPreImage<Account>();
var preImages = context.GetPreImages<Account>(); // For bulk operations
var postImage = context.GetPostImage<Account>();
var postImages = context.GetPostImages<Account>(); // For bulk operations
// Query information
var columnSet = context.GetColumnSet();
var isQuery = context.GetQuery(out QueryExpression query, out ColumnSet columns);
// Formatted context information
var stageName = context.GetFormattedExecutionStage(); // e.g., "PreOperation"
var modeName = context.GetFormattedExecutionMode(); // e.g., "Synchronous"
// Entity relationship operations
var relationship = context.GetRelationship();
var relatedEntities = context.GetRelatedEntities();
API Reference
Base Classes
PluginSkeleton
Abstract base class implementing IPlugin with built-in logging and exception handling.
| Member | Type | Description |
|---|---|---|
TimeProvider |
TimeProvider |
Encapsulates DateTime access for testability |
ExecuteInternal(serviceProvider) |
abstract void |
Implement your plugin logic here |
Executor
Abstract base class implementing IPlugin with simplified property access and stateless execution.
| Member | Type | Description |
|---|---|---|
Result |
ExecutionResult |
Get/set execution result |
Core |
IPluginExecutionContext |
Raw execution context |
Entity |
Entity |
Target entity (single operations) |
GetEntities() |
EntityCollection |
Target entities (bulk operations) |
PreEntityImage |
Entity |
Pre-image entity |
GetPreEntityImages() |
EntityCollection |
Pre-image entities (bulk) |
PostEntityImage |
Entity |
Post-image entity |
GetPostEntityImages() |
EntityCollection |
Post-image entities (bulk) |
SecuredOrganizationService |
IOrganizationService |
Cached service for current user |
ElevatedOrganizationService |
IOrganizationService |
Cached service with system privileges |
Execute() |
abstract ExecutionResult |
Implement your plugin logic here |
Extension Methods
ServiceProviderExtensions
Available on IServiceProvider:
GetExecutionContext() // IPluginExecutionContext7
GetOrganizationService() // IOrganizationService (current user)
GetOrganizationService(Guid userId) // IOrganizationService (specific user)
GetElevatedOrganizationService() // IOrganizationService (system)
GetTracingService() // ITracingService
GetLogger() // ILogger (default sinks)
GetLogger(params LogSink[] sinks) // ILogger (specific sinks)
GetTimeProvider() // TimeProvider
GetManagedIdentityService() // IManagedIdentityService
PluginExecutionContextExtensions
Available on IPluginExecutionContext:
GetTarget<T>() // T (typed entity)
GetTargets<T>() // IEnumerable<T> (bulk operations)
GetPreImage<T>() // T (typed pre-image)
GetPreImages<T>() // IEnumerable<T> (bulk pre-images)
GetPostImage<T>() // T (typed post-image)
GetPostImages<T>() // IEnumerable<T> (bulk post-images)
GetColumnSet() // ColumnSet
GetQuery(out QueryExpression, out ColumnSet) // bool
GetQuery(out QueryByAttribute, out ColumnSet) // bool
GetQuery(out FetchExpression, out ColumnSet) // bool
GetRelationship() // Relationship
GetRelatedEntities() // EntityReferenceCollection
GetFormattedExecutionStage() // string ("PreOperation", etc.)
GetFormattedExecutionMode() // string ("Synchronous", etc.)
GetInputParameter<T>(string key, out T value) // bool
GetOutputParameter<T>(string key, out T value) // bool
SetOutputParameter<T>(string key, T value) // void
GetRetrieveEntity() // Entity
GetRetrieveMultipleEntities() // EntityCollection
EntityAttributeExtension
Available on Entity:
HasAttribute(string attributeName) // bool
GetAttributeValue<T>(string attributeName, T defaultValue) // T
GetAttribute<T>(string attributeName) // T
Enums
ExecutionResult
Return value from Executor.Execute():
| Value | Description |
|---|---|
Ok |
Execution completed successfully |
Failure |
Execution failed |
Skipped |
Execution was skipped |
Examples
See the examples/SamplePlugin directory for complete working examples:
- VanillaSample.cs: Traditional IPlugin implementation
- SkeletonSample.cs: Using PluginSkeleton base class
- ExecutorSample.cs: Using Executor base class
Requirements
- .NET Framework 4.6.2 or higher
- Microsoft.Xrm.Sdk 9.0 or higher
- Microsoft.Extensions.Logging 6.0 or higher
License
Released under the Microsoft Public License (MS-PL).
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .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.Bcl.TimeProvider (>= 10.0.0)
- Microsoft.Extensions.Logging (>= 10.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0 | 48 | 7/2/2026 |
| 2.0.0-beta.1 | 38 | 7/2/2026 |