Plugin Packages¶
DGT-SRV-060 — Plugin packages (NuGet-based dependent assemblies) are the default for all
new server-side projects. ILMerge is not allowed — it was never officially supported by Dataverse, is no
longer maintained upstream, and plugin packages provide the same capability (and more) through
a supported mechanism.
Why plugin packages¶
- Bundle your plugin assembly together with any NuGet dependencies into a single
.nupkg, uploaded as one unit and stored in thePluginPackagetable. - No signing required (exception: plugins using a managed identity still need a strong-named assembly — see Project Setup → Signing).
- Supports including non-assembly resources (e.g. localized string files) alongside code, something ILMerge never handled cleanly.
- This is the path Microsoft is actively investing in; classic single-assembly registration is legacy at this point, not a parallel first-class option.
Creating a project¶
--skip-signing is the right default here — signing is for the classic format, not plugin
packages. If you're converting an existing classic plugin project instead of starting fresh,
expect to: switch to the SDK-style project format, re-add only the assembly references your
code actually needs (don't carry over a long historical reference list), and verify the
resulting .nupkg contents.
See Project Setup for the resulting .csproj shape.
Inspecting the package¶
Use NuGet Package Explorer
to drag-and-drop the built .nupkg and confirm its contents match expectations — in particular,
check for accidentally-included transitive dependencies (e.g. System.Web.Extensions) that
inflate the package without being needed; mark such references Private=false / not
copy-local if they're satisfied by the sandbox runtime already.
Size limits¶
- A plugin assembly (including custom workflow activities) must stay under 16 MB.
- As a best practice, consolidate related plugins and workflow activities into a single assembly as long as you stay under that limit — see Solution Architecture for how this interacts with solution layering.
- Packages with hundreds to thousands of
IPlugintypes take noticeably longer to import (observed: ~15 minutes for a thousand types) — this applies to every import path (API, web UI, Plugin Registration Tool), so don't assume a slow import is specific to one deployment method.
One owning solution¶
DGT-SRV-070 — A plugin package (and its assembly) belongs to exactly
one solution. Adding the same assembly to multiple unmanaged solutions invites duplicate step
registrations and solution-layer conflicts that are painful to untangle in target environments —
if another solution needs the plugin's behavior, it takes a dependency on the owning solution
(see Solution Architecture) rather than
containing the assembly itself.
Registering and updating¶
Use dgtp push rather than the Plugin
Registration Tool for anything beyond local, one-off experimentation:
dgtp push detects whether the package already exists in the target environment (by name and
version) and creates or updates it accordingly, then reconciles plugin types, steps, and step
images against your registration attributes. See
Versioning for why the package version must increase on every
pushed build, including local dev-loop pushes.
What this replaces¶
| Legacy approach | Replaced by |
|---|---|
| ILMerge / ILRepack | Plugin package dependent assemblies |
| Shared Projects for code reuse | NuGet package references inside the plugin package |
| Manual step registration in the Plugin Registration Tool | Registration Attributes + dgtp push |