dversedev

Reference

SDK attributes

Everything public in Dverse.Sdk — the only package a plugin project references. Every application is [Conditional("DVERSE_MANIFEST")]-stripped, so none of this reaches your IL: the compiler and the generator see the attributes, the .NET Framework runtime never does.

Attributes

StepAttribute

attributemethod · repeatable

Registers the method as a plugin step handler. The generator emits the IPlugin entry class and the manifest entry; the CLI diffs that manifest against the environment. Repeatable.

[Step(typeof(Account), Msg.Update, Stage.PreOperation,
    Filtering = new[] { Account.Cols.CreditLimit })]
StepAttribute(Type entity, string message, Stage stage) Typed form — entity is a generated model class.
StepAttribute(string entity, string message, Stage stage) String-entity form, for a table with no generated model. The handler takes the non-generic IStepContext.
StepAttribute(string message, Stage stage) Global (entity-less) message — a custom action, or the message an unbound custom API creates.
Type? Entity The model class, when the typed form was used.
string? EntityLogicalName The logical name, when the string-entity form was used.
string Message The SDK message. Use the Msg constants.
Stage Stage Pipeline stage.

StepAttribute<TEntity>

attributemethod · repeatable

The same registration as StepAttribute with the entity as a type argument. Identical manifest, key, step id and diagnostics — the two forms are interchangeable, neither is deprecated, and moving a step between them deploys as a no-op. Covers the model-class case only. Safe on net462 because every dverse attribute is [Conditional]-stripped, so the application never reaches IL and the Framework runtime never reflects over it.

[Step<Account>(Msg.Update, Stage.PreOperation)]
StepAttribute(string message, Stage stage) Message and stage; the entity is the type argument.
string Message The SDK message.
Stage Stage Pipeline stage.

StepAttributeSettings

abstract base

The settings shared by both [Step] forms. Never applied directly — it exists so the two cannot drift apart as settings are added.

ExecutionMode Mode Synchronous or Asynchronous.default Synchronous
int Rank Execution order among steps on the same message and stage.default 1
string[]? Filtering Columns that trigger the step. Update only; omitted or empty fires on all columns.
string? Key Stable identity used for environment matching and as the trace prefix. Set one where you want to rename freely.
string? Name Overrides the deterministic name template `dverse: {key}`. Must stay unique per assembly (DVERSE024). Max 256 characters.
string? Description Informational; shown in admin UIs. Participates in the diff like any other field. Max 256 characters.
string? Id Explicit sdkmessageprocessingstepid — the highest-precedence match.
bool AsyncAutoDelete Delete the async operation on success. Async steps only.default false
Deployment Deployment Deployment the step runs on.default ServerOnly
string? RunAsUser Impersonation: the systemuser id to execute as. Must be a GUID (DVERSE026). Note that user ids do not port between environments.
string? UnsecureConfig Deploy-time unsecure configuration, parsed into the handler's typed config parameter when one is declared.
string? SecureConfig Deploy-time secure configuration. Secure means admin-only read in Dataverse — the value still lives in source and the manifest.

ImageAttribute

attributemethod · repeatable

Explicit image column declaration — the escape hatch for when the column set cannot be inferred from the handler body. DVERSE021 points here. Normally you never write this: reading ctx.PreImage.X registers X.

ImageAttribute(ImageType type, params string[] columns) Image of exactly these columns.
ImageAttribute(ImageType type, ImageScope scope) Image scoped to all columns — a deliberate over-fetch.
ImageType Type Pre or Post.
string[] Columns The declared columns.
ImageScope Scope Columns or All.
string? Alias Registered entityalias — the key in PreEntityImages / PostEntityImages. Must be unique per step (DVERSE025).default "pre" / "post"

CustomApiAttribute

attributemethod

Registers the method as a Custom API main-operation handler. The request and response shapes are the method's record parameter and return type; their properties become the request-parameter and response-property rows.

CustomApiAttribute(string uniqueName) Prefixed unique name, e.g. "dverse_Reverse".
string UniqueName The API's unique name.
Type? BoundTo Model class of the bound entity. Omit for a global (unbound) API.
string? DisplayName Display name.
string? Description Description.

DeriveAttribute

attributemethod

Compute one column from other columns of the same row. One attribute compiles to Create and Update PreOperation steps; sources are inferred from the method body, all [Derive]s on an entity coalesce into one generated handler, and chained derivations are topologically ordered.

DeriveAttribute(string targetColumn) Logical name of the derived column — use a Cols constant.
string TargetColumn The derived column.
bool Enforce Also fire when the derived column itself changes, making the formula authoritative — manual edits are recomputed away. Default: manual edits survive until an input next changes.default false

RollupAttribute

attributemethod

Keep a parent column equal to an aggregate over its children, recomputed synchronously on child Create/Update/Delete — including reparenting, where old and new parent both recompute via an inferred pre-image of the lookup.

RollupAttribute(string targetColumn) The parent column holding the aggregate.
string TargetColumn The aggregate column.
string? Via The child lookup to roll up through. Required when several lookups target the parent (DVERSE071).

Children<TEntity>

compile-time helper

A compile-time-only view of a parent's child rows. [Rollup] bodies never execute: the expression — a documented Where/aggregate subset — compiles to one server-side FetchXML aggregate per affected parent, so the client cost is constant and rows are never iterated.

Children<TEntity> Where(Func<TEntity, bool> predicate) Restrict the child set.
int Count() Row count.
decimal Sum(Func<TEntity, decimal?> column) Sum of a column.
decimal? Min(Func<TEntity, decimal?> column) Minimum.
decimal? Max(Func<TEntity, decimal?> column) Maximum.
decimal? Avg(Func<TEntity, decimal?> column) Average.

CommandAttribute

attributemethod · repeatable

Generates a command-bar button next to a [CustomApi] handler — the button, its JavaScript and its registration. Setting any of the conditional-visibility properties changes how it deploys: Dataverse refuses appactionrule rows outside first-party solutions, so a conditioned command is emitted as a classic ribbon fragment with EnableRules the platform does support.

CommandAttribute(Type entity, string label) Button on an entity's command bar.
CommandAttribute(string label) Button with no entity context.
Type? Entity The entity the button belongs to.
string Label Button label.
Ribbon Location Where the button appears.default Form
string? Key Stable identity for matching.
string? Icon Icon name.
string? IconWebResource Icon web resource unique name.
string? Tooltip Tooltip text.
string? Description Description.
string? AccessibilityText Screen-reader text.
int Sequence Ordering within the bar. Left undeclared, the server does not stamp one.default -1
bool Hidden Statically hidden.default false
When EnableWhen Enable on new records, existing records, or always.default Always
string? EnableWhenJs Custom JavaScript enable rule.
bool EnableWhenJsDefault Value assumed before the custom rule has evaluated.default false
string? EnableWhenField Enable when this field is truthy.
string? EnableWhenNotEmpty Enable when this column has a value.
string? EnableWhenEmpty Enable when this column is empty.
int RequireSelection Minimum selected rows required (grid commands).default 0
string? Confirm Confirmation prompt shown before running.
string? ConfirmTitle Confirmation dialog title.
string? ConfirmButton Confirmation dialog button label.
string? Progress Progress indicator text.
string? Success Success message. Supports {response.X} placeholders.
SuccessStyle SuccessStyle Toast, Dialog or None.default Toast
Refresh Refresh What to refresh afterwards.default Default
Navigate Navigate Where to navigate afterwards.default None
string? NavigateTarget Navigation target.
string? Before Lifecycle hook run before the call.
string? After Lifecycle hook run after the call.
string? OnError Lifecycle hook run on failure.
string? Handler Full override — your own JavaScript function replaces the generated body.

FetchAttribute

attributemethod

Declares the columns a bound custom API's entity should be fetched with, when the set cannot be inferred from the handler body. DVERSE022 points here.

FetchAttribute(params string[] columns) Fetch exactly these columns.
FetchAttribute(FetchScope scope) Fetch all columns.
string[] Columns The declared columns.
FetchScope Scope Columns or All.

JobAttribute

attributemethod

Marks a method as an async job body, enqueued through ctx.Async. dverse creates the dverse_job table and generates the dispatcher; retries and dead-lettering are handled for you.

int MaxAttempts Attempts before the job is dead-lettered.default 1
string? Key Stable identity for the job.

SecureAttribute

attributeparameter

Marks a handler's config parameter as the secure configuration rather than the unsecure one.

WorkflowActivityAttribute

attributeclass

Registers the class as a custom workflow activity, so it appears in the classic workflow designer.

string? Name Display name.
string? Group Group the activity is listed under.

LocalizedStringsAttribute

attributeassembly

Points the runtime at a RESX base name, which is what ctx.FailLocalized resolves messages against.

LocalizedStringsAttribute(string baseName) Resource base name.
string BaseName The resource base name.

Messages

Msg

static constants

The SDK message names, so a typo is a compile error rather than a deploy-time surprise.

Msg.Create "Create"
Msg.Update "Update"
Msg.Delete "Delete"
Msg.Retrieve "Retrieve"
Msg.RetrieveMultiple "RetrieveMultiple"
Msg.Assign "Assign"
Msg.SetState "SetState"
Msg.Associate "Associate"
Msg.Disassociate "Disassociate"

Enums

Stage

enum

Pipeline stage. Values match the platform's own.

PreValidation = 10 Before the database transaction opens.
PreOperation = 20 Inside the transaction, before the main operation.
PostOperation = 40 Inside the transaction, after the main operation.

ExecutionMode

enum

Synchronous or asynchronous execution.

Synchronous = 0 Runs in the caller's transaction.
Asynchronous = 1 Queued. Valid only on PostOperation (DVERSE001).

Deployment

enum

Which deployment the step executes on. Only relevant to mobile-offline and Outlook-offline organizations.

ServerOnly = 0 Server only — the default.
OfflineOnly = 1 Offline client only.
Both = 2 Server and offline client.

ImageType

enum

Image kind. Values match sdkmessageprocessingstepimage.imagetype.

Pre = 0 Row state before the operation. Invalid on Create (DVERSE002).
Post = 1 Row state after the operation. PostOperation only.

ImageScope

enum

How an explicit [Image] chooses its columns.

Columns = 0 Only the columns listed on the attribute.
All = 1 All columns — attributes = null on the image row.

FetchScope

enum

How an explicit [Fetch] chooses its columns.

Columns = 0 Only the columns listed.
All = 1 All columns.

Ribbon

enum

Where a [Command] button appears.

Form = 0 Record form command bar.
MainGrid = 1 Main grid.
SubGrid = 2 Sub-grid on a form.
AssociatedGrid = 3 Associated-records grid.
QuickForm = 4 Quick-view form.
GlobalHeader = 5 Global header.
Dashboard = 6 Dashboard.

Refresh

enum

What a [Command] refreshes after it succeeds.

Default = 0 The sensible default for the location.
Form = 1 Reload the form.
Grid = 2 Refresh the grid.
None = 3 Refresh nothing.
SaveThenRefresh = 4 Save the record, then refresh.

When

enum

Record state a [Command] is enabled for.

Always = 0 Always enabled.
ExistingRecord = 1 Saved records only.
NewRecord = 2 Unsaved records only.

SuccessStyle

enum

How a [Command] reports success.

Toast = 0 Transient toast.
Dialog = 1 Modal dialog.
None = 2 Say nothing.