Callouts to plug-ins: CRM 3.0, 4.0, 2011 and Dataverse side by side
How custom server code changed from CRM 3.0 callouts to CRM 4.0 plug-ins, what CRM 2011 changed again, and what carries through to Dataverse. Includes what broke at each upgrade and how to port an old callout.
Answer first
Custom server code went through three shapes before Dataverse:
- CRM 3.0 callouts. A class derived from
CrmCalloutBase, listed by hand incallout.config.xmlin each server’s assembly folder, with pre and post methods for a fixed set of events. Synchronous only. - CRM 4.0 plug-ins. A class implementing
IPlugin, registered as records in the organization using the SDK’s sample tools. Two custom stages, a parent and a child pipeline, synchronous or asynchronous, and loop detection. - CRM 2011 plug-ins. The same idea with a new
Executesignature, the parent and child pipelines merged into numbered stages, and a sandbox that let plug-ins run in CRM Online.
Upgrade support stepped down one version at a time. CRM 4.0 still ran 3.0 callouts, with changed behaviour. CRM 2011 ran 4.0 plug-ins but not 3.0 callouts. CRM 2013 stopped running 4.0 plug-ins.
This page draws on Microsoft’s CRM 3.0, 4.0 and 2011 SDKs, its archived CRM 2013 documentation, and current Dataverse documentation. Each section names its sources.
Side by side
Sources: the CRM 3.0 SDK, the CRM 4.0 SDK, the CRM 2011 SDK, and Microsoft’s current Dataverse plug-in documentation. A dash means this site hasn’t sourced that cell yet, not that the answer is “nothing”.
| CRM 3.0 callouts | CRM 4.0 plug-ins | CRM 2011 plug-ins | Dataverse plug-ins | |
|---|---|---|---|---|
| Code | Derive from CrmCalloutBase, override one method per event |
Implement IPlugin.Execute(IPluginExecutionContext) |
IPlugin with a new Execute signature |
IPlugin.Execute(IServiceProvider) |
| Registration | Hand-edited callout.config.xml on every server |
Records created through SDK classes; sample tools shipped as source | Records; the Plug-in Registration tool, ready-built from SDK 5.0.13 | Plug-in Registration tool, opened with pac tool prt, or Power Platform Tools |
| Where the assembly lives | On disk, in server\bin\assembly |
Database (recommended) or on disk | Database or disk on-premises; database in the sandbox | Database, sandbox only |
| When it runs | Pre and post methods on 14 named events | Pre-event or post-event stage, in the parent or child pipeline | Numbered stages in one pipeline | Numbered stages; see event pipeline stages |
| Synchronous or asynchronous | Synchronous only | Either | Either | Either |
| Stopping the operation | Pre-callout returns Stop or Abort |
Throw InvalidPluginExecutionException from a pre-event plug-in |
— | Throw InvalidPluginExecutionException |
| Configuration | Assembly, class, onerror, timeout, pre/post attribute lists |
Unsecure and secure strings passed to the constructor | — | Unsecure and secure strings passed to the constructor |
| Instances | New instance for every call | Cached and reused across threads, so must be stateless | — | Cached and reused, so must be stateless |
| Loop protection | None; the SDK gives design advice | Infinite loop detection, carried by a correlation token | — | — (the context properties involved are covered on Depth, ParentContext and CorrelationId) |
| Runs as | CRMAppPool identity; impersonate with CallerId |
CRMAppPool identity; impersonating user set on the step, or chosen in code |
— | The calling user, a user set on the step, or impersonation in code |
| CRM Online | Not applicable | Not supported | Supported in the sandbox | Online only |
What changed at each upgrade
CRM 3.0 to 4.0
Source: the CRM 4.0 SDK.
Callouts kept working, but the 4.0 SDK calls them a deprecated model, and some behaviour changed:
- Plug-ins run first. In any stage, registered plug-ins run before
callouts, so a callout’s
StoporAbortcan’t prevent them. Stopbehaves likeAbort, but the user sees a standard error message.onerroris ignored. Exceptions from callouts are always shown.- Callout instances are cached and shared across threads. Class-level variables that were safe in 3.0 can now corrupt data.
- Some state changes raise new messages. Closing a case raises
CloseIncident, not a set-state event. - Multiple organizations. Callouts are directed to the default organization.
- No new capabilities. Callouts get no asynchronous execution, database deployment, rich context or infinite loop detection. The SDK advises upgrading any callout you need to change to the 4.0 model.
CRM 4.0 to 2011
Source: the CRM 2011 SDK.
- 4.0 plug-ins keep running without a rebuild, but can’t use the sandbox or tracing, and are registered with the 4.0 SDK’s tool.
- 3.0 callouts don’t run at all.
- The pipelines merged. A 4.0 pre-event step in the parent pipeline corresponds to stage 10, and in the child pipeline to stage 20.
- Registration is validated. Invalid step and image settings that 4.0 quietly ignored make solution imports fail after the upgrade, so fix them first.
- To rebuild on the 2011 SDK:
IPlugin.Executehas a new signature;CallerOrigingives way toIsExecutingOfflineandIsOfflinePlayback, andIsInTransactionis new;- catch
FaultException<OrganizationServiceFault>; - some messages are replaced, such as
AssociateRequestforAssociateEntitiesRequest; - assemblies must be signed.
CRM 2011 to 2013, and on to Dataverse
Sources: Microsoft’s archived CRM 2013 documentation, and current Dataverse documentation.
- CRM 2013 doesn’t run 4.0 plug-ins or custom workflow activities. Anything still on the 4.0 model has to be rewritten against the 2011 interfaces before upgrading. See the CRM 2013 page.
- Dataverse runs plug-ins only in the sandbox, stored in the database, with a time limit and assemblies up to 16 MB. See the Dataverse page.
Porting an old callout
Sources: the CRM 3.0, 4.0 and 2011 SDKs.
If you inherit a callout, it can’t simply be registered on anything newer than 4.0. Each part of it maps to something in the plug-in model:
| In the callout | In a plug-in |
|---|---|
A callout.config.xml entry of entity and event |
A registered step: message, entity, stage and mode |
prevalue and postvalue attribute lists |
Pre-image and post-image registered on the step |
PreCalloutReturnValue.Abort with errorMessage |
Throw InvalidPluginExecutionException with the message, from a stage before the core operation |
PreCalloutReturnValue.Stop |
No quiet equivalent; an exception with a clear message |
Changing entityXml in a pre-callout |
Change the target entity in the context before the core operation |
| Class-level fields | None: keep state in the context, because instances are cached |
CallerId impersonation from userContext.UserId |
The step’s run-as user, or impersonation in code |
| Loop guards such as a flag field or a dedicated user | Platform loop detection, plus your own check of the context’s depth |
| A set-state callout on some entities | Check which message 4.0 and later raise, for example CloseIncident |
onerror="ignore" |
Catch the exception inside the plug-in |
Three rows are this site’s reading rather than a Microsoft mapping:
Stophaving no quiet equivalent;- the depth check;
- catching exceptions in place of
onerror="ignore".
They follow from the sourced behaviour above, but Microsoft never published a callout-to-plug-in porting table.
Sources
- Use plug-ins to extend business processes (Dataverse) Microsoft’s plug-in overview for Dataverse: declarative options first, synchronous and asynchronous registration, the alternatives (workflow activities, calculated and rollup columns, custom actions, Service Bus and webhooks, Power Automate), and a hard time limit on plug-in execution.
- Write a plug-in (Dataverse) Microsoft’s plug-in how-to: Power Platform Tools for Visual Studio and the Power Platform CLI as the modern routes, stateless IPlugin classes because instances are cached, secure and unsecure configuration, the optional generated PluginBase class, and the Web API not being supported inside plug-ins.
- Build and package plug-in code (Dataverse) Microsoft’s packaging constraints for plug-ins: a 16 MB assembly limit, signing when dependent assemblies aren’t used, the dependent assemblies capability as a NuGet package stored in the PluginPackage table, and no support for ILMerge.
- Register a plug-in (Dataverse) Microsoft’s plug-in registration guide. Isolation mode and assembly location options apply to on-premises only; for Dataverse always accept Sandbox and Database.
- Troubleshoot Dataverse plug-ins Microsoft’s plug-in troubleshooting guide, including “Sandbox Worker process crashed” (error code -2147204723) and its four usual causes, and errors due to user privileges inside plug-ins, handled by registering the step to run as a user with the privileges or by impersonation.
- Microsoft CRM 3.0 SDK (compiled help, crmsdk3_0.chm, 2007 edition) Private archive: CRM-SDK-Rescue/3.0-SDK/crmsdk3_0.chm Microsoft’s SDK help for CRM 3.0: the Server Programming Guide’s callout model, method signatures, callout.config.xml reference, error handling and tracing, and the CrmService and MetadataService web services at /mscrmservices/2006/, including security, impersonation, DynamicEntity, FetchXML and QueryExpression. The owner’s copy came from a third-party software archive; it is a valid help file whose 6,937 pages all carry Microsoft’s 2007 copyright. Read as documents only, never executed. Quote sparingly and cite; do not republish.
- Microsoft Dynamics CRM 4.0 SDK (compiled help, CrmSdk4.chm, version 4.0.13, November 2010) Private archive: CRM-SDK-Rescue/4.0-SDK/sdk/crmsdk4.chm Microsoft's SDK help for CRM 4.0 Update Rollup 13 and CRM Online: plug-in development (IPlugin, the execution context, the unsecure and secure constructor strings), the event execution pipeline and its parent and child pipelines, registration and deployment, impersonation, error handling, offline plug-ins, execution of CRM 3.0 callouts, the 2006 endpoint, and what is new in the 4.0 web services. Extracted without running anything from CrmSdk4.exe, whose Microsoft Authenticode signature is valid and which the Internet Archive captured from download.microsoft.com. All 12,022 pages carry Microsoft's copyright. Quote sparingly and cite; do not republish.
- Microsoft Dynamics CRM 2011 SDK (compiled help, CrmSdk2011.chm) Private archive: CRM-SDK-Rescue/2011-SDK_from_desk/SDK/CrmSdk2011.chm Microsoft's own SDK help for the 2011 release, from an owner-held copy. Static reading only; the package is never executed and is not part of this repository. Quote sparingly and cite; do not republish.
- Upgrade plug-ins and custom workflow activities (Microsoft Dynamics CRM 2013 SDK, archived) Microsoft’s archived guidance on moving CRM 4.0-style plug-ins and custom workflow activities to CRM 2013: the changed IPlugin signature, CallerOrigin replaced by IsExecutingOffline and IsOfflinePlayback, IsInTransaction, FaultException<OrganizationServiceFault>, AssociateRequest replacing AssociateEntitiesRequest, signed assemblies, and CodeActivity with the Microsoft.Xrm.Sdk.Workflow namespaces.