Skip to main content

Libraries Reference

The Power Platform Developer Suite (PPDS) ships a set of focused .NET libraries you can compose in your own applications. PPDS.Auth resolves credentials, PPDS.Dataverse manages connection pools and bulk operations on top of that, PPDS.Migration layers dependency-aware export and import on top of the pool, and PPDS.Plugins is a standalone net462 package of attributes for declarative plugin registration. The CLI, MCP server, and VS Code extension are all built on these same libraries.

Packages

PackageVersionTargetDescription
PPDS.Auth1.0.0-beta.8net8.0;net9.0;net10.0Credential providers, auth profiles, DPAPI-encrypted credential store
PPDS.Dataverse1.0.0-beta.7net8.0;net9.0;net10.0Connection pooling, bulk operations, throttle-aware resilience
PPDS.Migration1.0.0-beta.8net8.0;net9.0;net10.0Parallel exporter and tiered importer over CMT-format archives
PPDS.Plugins2.1.0-beta.1net462Declarative attributes for plugin steps, images, and Custom APIs

The net462 target on PPDS.Plugins is required for plugin assembly compatibility with the Dataverse sandbox. The other packages are multi-targeted at current LTS and STS .NET releases.

PPDS.Auth

Handles credential acquisition, profile storage, and token caching. Profiles are persisted to disk with DPAPI encryption on Windows and platform keychain integration on other OSes.

Installation

dotnet add package PPDS.Auth

Key types

TypePurpose
ICredentialProviderAbstraction over all auth flows; returns authenticated ServiceClient
CredentialProviderFactoryBuilds an ICredentialProvider from an AuthProfile
AuthMethodEnum of supported flows (9 total — see below)
AuthProfileSerialized profile with environment URL, tenant, and auth method
ProfileStoreFile-backed profile collection
ISecureCredentialStore / NativeCredentialStorePlatform-specific secret storage
ProfileEncryptionDPAPI wrapper used by the profile store
IGlobalDiscoveryServiceResolves Dataverse environments via Global Discovery

Supported AuthMethod values: InteractiveBrowser, DeviceCode, ClientSecret, CertificateFile, CertificateStore, ManagedIdentity, GitHubFederated, AzureDevOpsFederated, UsernamePassword.

Usage

Register the shared singletons in DI, then create a provider from a profile:

using Microsoft.Extensions.DependencyInjection;
using PPDS.Auth.Credentials;
using PPDS.Auth.DependencyInjection;
using PPDS.Auth.Profiles;

var services = new ServiceCollection();
services.AddAuthServices();

var provider = services.BuildServiceProvider();
var profileStore = provider.GetRequiredService<ProfileStore>();
var credentialStore = provider.GetRequiredService<ISecureCredentialStore>();

var profile = profileStore.Get("dev");
using var credentials = await CredentialProviderFactory.CreateAsync(profile, credentialStore);

using var client = await credentials.CreateServiceClientAsync(profile.EnvironmentUrl);

AddAuthServices registers ProfileStore, EnvironmentConfigStore, and ISecureCredentialStore as singletons. They are file-backed and intended to be shared for the lifetime of the process.

PPDS.Dataverse

Connection pooling, bulk operation wrappers, throttle detection, and metadata queries over the Dataverse SDK. Pool connections are keyed by application user, and the pool tracks live degrees-of-parallelism hints from each connection so multi-tenant batch workloads stay within service-protection limits.

Installation

dotnet add package PPDS.Dataverse

Key types

TypePurpose
IDataverseConnectionPoolCheckout-based pool with DOP tracking, throttle retries, and ExecuteAsync helper
IPooledClientScoped pool checkout — returns to pool on dispose
DataverseOptions / DataverseConnectionConfiguration shape for the pool
IBulkOperationExecutorCreateMultiple / UpdateMultiple / UpsertMultiple / DeleteMultiple wrappers
IMetadataQueryServiceCached entity and attribute metadata
IQueryExecutorQuery execution with pagination
IThrottleTrackerPer-connection throttle state

Usage

using Microsoft.Extensions.DependencyInjection;
using PPDS.Dataverse.BulkOperations;
using PPDS.Dataverse.Configuration;
using PPDS.Dataverse.DependencyInjection;
using PPDS.Dataverse.Pooling;

var services = new ServiceCollection();
services.AddDataverseConnectionPool(options =>
{
options.Connections.Add(new DataverseConnection("Primary", connectionString));
options.Pool.MaxPoolSize = 50;
});

var provider = services.BuildServiceProvider();
var pool = provider.GetRequiredService<IDataverseConnectionPool>();
var bulk = provider.GetRequiredService<IBulkOperationExecutor>();

await pool.EnsureInitializedAsync();

var result = await bulk.CreateMultipleAsync(
entityLogicalName: "contact",
entities: contacts,
options: new BulkOperationOptions { BatchSize = 1000 });

AddDataverseConnectionPool has an overload that binds from IConfiguration, including multi-environment configs — see the XML docs on ServiceCollectionExtensions for the full configuration schema.

PPDS.Migration

Parallel export and dependency-ordered import over CMT-format ZIP archives. Migration does not take raw connection strings — it resolves IExporter and IImporter from DI on top of a PPDS.Dataverse connection pool.

Installation

dotnet add package PPDS.Migration

Key types

TypePurpose
IExporter (default: ParallelExporter)Reads a schema and writes a CMT ZIP
IImporter (default: TieredImporter)Dependency-graph import with resumable phases
ExportOptions / ImportOptionsParallelism, bypass flags, date shifting, user mapping
ISchemaGeneratorBuilds a MigrationSchema from Dataverse metadata
IProgressReporterStreams phase and entity progress
ExportResult / ImportResultCounts, warnings, errors, timing

IExporter.ExportAsync takes (string schemaPath, string outputPath, ExportOptions? options, IProgressReporter? progress, CancellationToken cancellationToken) and returns Task<ExportResult>. IImporter.ImportAsync takes (string dataPath, ImportOptions? options, IProgressReporter? progress, CancellationToken cancellationToken) and returns Task<ImportResult>. Both interfaces also expose overloads that take pre-parsed MigrationSchema / MigrationData + ExecutionPlan for reuse across multiple runs.

Usage

using Microsoft.Extensions.DependencyInjection;
using PPDS.Dataverse.Configuration;
using PPDS.Dataverse.DependencyInjection;
using PPDS.Migration.DependencyInjection;
using PPDS.Migration.Export;
using PPDS.Migration.Import;

var services = new ServiceCollection();
services.AddDataverseConnectionPool(options =>
{
options.Connections.Add(new DataverseConnection("Primary", connectionString));
});
services.AddDataverseMigration();

var provider = services.BuildServiceProvider();
var exporter = provider.GetRequiredService<IExporter>();
var importer = provider.GetRequiredService<IImporter>();

var exportResult = await exporter.ExportAsync(
schemaPath: "./schema.xml",
outputPath: "./export/data.zip",
options: new ExportOptions { MaxDegreeOfParallelism = 8 });

var importResult = await importer.ImportAsync(
dataPath: "./export/data.zip",
options: new ImportOptions { BypassCustomPluginExecution = true });

AddDataverseMigration throws InvalidOperationException if AddDataverseConnectionPool has not been called first — the importer and exporter require a registered IDataverseConnectionPool.

PPDS.Plugins

Attribute-based plugin registration. Decorate your plugin classes and the CLI (or your own tooling) reads the attributes to register steps, images, and Custom APIs against Dataverse. The package targets net462 to match the Dataverse plugin sandbox.

Installation

dotnet add package PPDS.Plugins

Attributes and enums

TypePurpose
PluginStepAttributeMessage, entity, stage, mode, filtering, impersonation, bypass, invocation source
PluginImageAttributePre/post images, attributes, entity alias, step linkage
CustomApiAttributeCustom API unique name, binding, function/action, privilege
CustomApiParameterAttributeRequest/response parameters for a Custom API
PluginStage, PluginMode, PluginImageTypeStep configuration enums
PluginDeployment, PluginInvocationSourceDeployment target and pipeline source (new in 2.1)
ApiBindingType, ApiParameterType, ParameterDirection, ApiProcessingStepTypeCustom API enums (new in 2.1)

What's new in 2.1

PluginStepAttribute gained Deployment, RunAsUser, CanBeBypassed, CanUseReadOnlyConnection, and InvocationSource properties. CustomApiAttribute and CustomApiParameterAttribute add full Custom API authoring. Existing 2.0 plugins compile unchanged.

Usage

using Microsoft.Xrm.Sdk;
using PPDS.Plugins;

[PluginStep(
Message = "Update",
EntityLogicalName = "account",
Stage = PluginStage.PostOperation,
Mode = PluginMode.Synchronous,
FilteringAttributes = "name,telephone1",
CanUseReadOnlyConnection = false)]
[PluginImage(
ImageType = PluginImageType.PreImage,
Name = "PreImage",
Attributes = "name,telephone1,revenue")]
public class AccountUpdatePlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// context.PreEntityImages["PreImage"] is populated by the registered image
}
}

[CustomApi(
UniqueName = "ppds_ProcessOrder",
DisplayName = "Process Order",
BindingType = ApiBindingType.Global)]
[CustomApiParameter(
Name = "OrderId",
Type = ApiParameterType.Guid,
Direction = ParameterDirection.Input)]
[CustomApiParameter(
Name = "ConfirmationNumber",
Type = ApiParameterType.String,
Direction = ParameterDirection.Output)]
public class ProcessOrderPlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider) { /* ... */ }
}

Versioning

Each library is versioned independently and follows semantic versioning. PPDS.Plugins is on the 2.x line because the 1.x attribute surface has shipped; the other libraries are in 1.0 beta. The PPDS CLI pins specific library versions per release, so upgrading the CLI is the simplest way to stay on a known-good set.

Breaking changes are listed in each package's CHANGELOG.md in the main repo: PPDS.Auth, PPDS.Dataverse, PPDS.Migration, PPDS.Plugins.

Next steps