XrmGhost.Attributes
1.0.2
dotnet add package XrmGhost.Attributes --version 1.0.2
NuGet\Install-Package XrmGhost.Attributes -Version 1.0.2
<PackageReference Include="XrmGhost.Attributes" Version="1.0.2" />
<PackageVersion Include="XrmGhost.Attributes" Version="1.0.2" />
<PackageReference Include="XrmGhost.Attributes" />
paket add XrmGhost.Attributes --version 1.0.2
#r "nuget: XrmGhost.Attributes, 1.0.2"
#:package XrmGhost.Attributes@1.0.2
#addin nuget:?package=XrmGhost.Attributes&version=1.0.2
#tool nuget:?package=XrmGhost.Attributes&version=1.0.2
XrmGhost.Attributes
XrmGhost.Attributes is a .NET library of custom attributes for declarative Dataverse plugin development. Decorate your plugin classes with these attributes to declare execution context, message handling, entity images, input/output parameters, and configuration — without writing plumbing code.
The package targets netstandard2.0 and has no runtime dependencies beyond the BCL, so it can be referenced by any Dataverse plugin project.
Current version: 0.6.27
Table of Contents
Standalone Use
You can reference XrmGhost.Attributes in any Dataverse plugin project — no other XrmGhost component is required.
The attributes are pure .NET attribute classes. Adding them to your plugin decorates the assembly with structured metadata that can be read at runtime or build time via reflection. On their own they impose zero runtime overhead inside the Dataverse sandbox: a [PreImage] or [InputParameter] attribute on a class does nothing unless something reads it.
Typical standalone uses:
- Custom tooling. Write a registration or scaffolding tool that reads attributes to automate plugin step registration.
- Documentation generation. Produce an audit of all messages, entities, and images a plugin assembly handles, without parsing code.
- Test harnesses. Read
[InputParameter]and[PreImage]attributes to reconstruct a plausibleIPluginExecutionContextin unit tests.
XrmGhost Ecosystem
Within the XrmGhost ecosystem this package is consumed by two components:
xrmghost-framework-host
xrmghost-framework-host is a thin hosting layer that wraps plugin execution. At runtime it reads the attributes on a plugin class via reflection and automatically populates the corresponding properties before calling Execute. This removes the standard boilerplate of extracting Target, pre/post images, and configuration strings from IPluginExecutionContext.
xrmghost-cli — generate-scenario
The generate-scenario command of the XrmGhost CLI introspects a plugin assembly and generates test scenario files. It uses the attribute values (entity JSON, parameter JSON, image aliases) as the starting data for each scenario.
Note:
generate-scenarioexpects plugins to be decorated with XrmGhost.Attributes attributes. If the attributes are absent the CLI degrades gracefully with a warning, but no scenario data will be pre-populated.
Installation
1. Configure the GitHub Packages NuGet source
XrmGhost.Attributes is published to GitHub Packages. You must add the source before installing:
dotnet nuget add source https://nuget.pkg.github.com/xrmghost/index.json \
--name github-xrmghost \
--username YOUR_GITHUB_USERNAME \
--password YOUR_GITHUB_PAT
Replace YOUR_GITHUB_USERNAME with your GitHub username and YOUR_GITHUB_PAT with a Personal Access Token that has the read:packages scope.
2. Add the package
dotnet add package XrmGhost.Attributes --version 0.6.27
Or add the reference directly to your .csproj:
<PackageReference Include="XrmGhost.Attributes" Version="0.6.27" />
Included Attributes
All attributes target AttributeTargets.Class — they must be placed on the plugin class, not on individual members.
| Attribute | Description |
|---|---|
PluginExecutionConfigAttribute |
Declares entity + messages the plugin handles; supports stage, mode, and impersonation. Repeatable. |
HandlesMessageAttribute |
Declares a single SDK message the plugin handles. Repeatable. |
InputParameterAttribute |
Declares an input parameter name and its default JSON value. Repeatable. |
OutputParameterAttribute |
Declares an expected output parameter name and its expected JSON value. Repeatable. |
PreImageAttribute |
Declares a pre-operation entity image alias and its JSON seed value. Repeatable. |
PostImageAttribute |
Declares a post-operation entity image alias and its JSON seed value. Repeatable. |
SecureConfigurationAttribute |
Declares the default secure configuration string. Single use. |
UnsecureConfigurationAttribute |
Declares the default unsecure configuration string. Single use. |
SharedVariableAttribute |
Declares a shared variable name and its default JSON value. Repeatable. |
SolutionComponentAttribute |
Declares which solution(s) the plugin should be registered in. Repeatable. |
Usage Examples
All attributes live in the XrmGhost.Attributes namespace.
Basic plugin — single entity, multiple messages
using XrmGhost.Attributes;
using Microsoft.Xrm.Sdk;
[PluginExecutionConfigAttribute("account", "Create", "Update")]
[PreImageAttribute("primary", "{ \"__entityName\": \"account\", \"accountid\": \"00000000-0000-0000-0000-000000000001\", \"name\": \"Old Name\" }")]
[InputParameterAttribute("Target", "{ \"__entityName\": \"account\", \"accountid\": \"00000000-0000-0000-0000-000000000001\" }")]
public class AccountPlugin : IPlugin
{
public Entity TargetEntity { get; set; }
public Entity PreImageEntity { get; set; }
public void Execute(IServiceProvider serviceProvider)
{
// When used with xrmghost-framework-host, TargetEntity and PreImageEntity
// are populated automatically before Execute is called.
}
}
Multiple entities and messages
using XrmGhost.Attributes;
using Microsoft.Xrm.Sdk;
[PluginExecutionConfigAttribute("account", "Create", "Update")]
[PluginExecutionConfigAttribute("contact", "Create")]
[PluginExecutionConfigAttribute("opportunity", "Update", "Delete")]
[InputParameterAttribute("Target", "{ \"__entityName\": \"account\", \"accountid\": \"00000000-0000-0000-0000-000000000001\" }")]
public class MultiEntityPlugin : IPlugin
{
public Entity TargetEntity { get; set; }
public void Execute(IServiceProvider serviceProvider)
{
// Registered for:
// Account — Create, Update
// Contact — Create
// Opportunity — Update, Delete
}
}
Column-filtered entity images
Filtering images to specific columns improves performance by reducing the payload transmitted to the plugin.
using XrmGhost.Attributes;
using Microsoft.Xrm.Sdk;
[PluginExecutionConfigAttribute("account", "Update")]
[InputParameterAttribute("Target", "{ \"__entityName\": \"account\", \"accountid\": \"00000000-0000-0000-0000-000000000001\" }")]
[PreImageAttribute("primary", "{ \"__entityName\": \"account\", \"name\": \"Old Name\", \"revenue\": 1000.00 }",
Attributes = new[] { "name", "accountid", "createdon", "revenue" })]
[PostImageAttribute("updated", "{ \"__entityName\": \"account\", \"name\": \"New Name\", \"revenue\": 2000.00 }",
Attributes = new[] { "name", "modifiedon", "revenue" })]
public class AccountUpdatePlugin : IPlugin
{
public Entity TargetEntity { get; set; }
public Entity PreImageEntity { get; set; }
public Entity PostImageEntity { get; set; }
public void Execute(IServiceProvider serviceProvider) { }
}
Stage, mode, and user impersonation
using XrmGhost.Attributes;
using Microsoft.Xrm.Sdk;
[PluginExecutionConfigAttribute("lead", "Create", "Update",
Stage = 20, Mode = 0,
ImpersonatingUserId = "12345678-1234-1234-1234-123456789012")]
[SolutionComponentAttribute("LeadManagement")]
[InputParameterAttribute("Target", "{ \"__entityName\": \"lead\", \"leadid\": \"00000000-0000-0000-0000-000000000002\" }")]
public class LeadProcessorPlugin : IPlugin
{
public Entity TargetEntity { get; set; }
public void Execute(IServiceProvider serviceProvider) { }
}
Stage values: 10 PreValidation · 20 PreOperation · 40 PostOperation.
Mode values: 0 Synchronous · 1 Asynchronous.
Multiple solutions
using XrmGhost.Attributes;
using Microsoft.Xrm.Sdk;
[SolutionComponentAttribute("CoreCRM", IsDefault = true)]
[SolutionComponentAttribute("SalesEnhancements")]
[PluginExecutionConfigAttribute("opportunity", "Create", "Update", "Delete")]
[InputParameterAttribute("Target", "{ \"__entityName\": \"opportunity\", \"opportunityid\": \"00000000-0000-0000-0000-000000000003\" }")]
public class OpportunityPlugin : IPlugin
{
public Entity TargetEntity { get; set; }
public void Execute(IServiceProvider serviceProvider) { }
}
Input and output parameters with shared variables
using XrmGhost.Attributes;
using Microsoft.Xrm.Sdk;
[PluginExecutionConfigAttribute("none", "CalculatePrice")]
[InputParameterAttribute("Quantity", "5")]
[InputParameterAttribute("UnitPrice", "19.99")]
[OutputParameterAttribute("TotalPrice", "99.95")]
[SharedVariableAttribute("PricingRuleVersion", "\"v2\"")]
public class CalculatePricePlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider) { }
}
Secure and unsecure configuration
using XrmGhost.Attributes;
using Microsoft.Xrm.Sdk;
[PluginExecutionConfigAttribute("account", "Create")]
[SecureConfigurationAttribute("{ \"apiKey\": \"secret-value\" }")]
[UnsecureConfigurationAttribute("{ \"endpoint\": \"https://example.com/api\" }")]
public class ConfiguredPlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider) { }
}
Contributing
Contributions are welcome. Please refer to CONTRIBUTING.md for guidelines.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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 Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.Text.Json (>= 9.0.7)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.