Case study

Modernizing a 96-activity Dynamics 365 workflow assembly without breaking existing workflows

The challenge

Workflow Tools for Dynamics 365 is a widely used open-source assembly of custom workflow activities (Clone Record, Query Values, Set Process, Share Record, JSON Parser and many more). It started in 2015 and has grown through many contributors to 96 activities that organizations depend on inside their classic workflows.

Years of accumulated change left the usual problems: duplicated helper code, inconsistent error handling, a bundled third-party library, and no systematic way to prove that an upgrade wouldn't break the workflows already built on top of it.

Custom workflow activities are hard to upgrade because the workflows that use them are the contract. Rename an argument or change an output format, and production workflows fail with no compile-time warning.

What we did

Refactored the code

  • Merged duplicate helper projects into a single shared library.
  • Added a common activity base class and standardized tracing and exception handling.
  • Moved activities to thin entry points that read inputs, call one shared method and set outputs.
  • Replaced internal FetchXML with QueryExpression, removed dead code, and fixed blocking HTTP calls.
  • Replaced a bundled library copy with the Newtonsoft.Json package, merged into the single deployable assembly with ILRepack, because Dataverse loads only the registered assembly.

Built an upgrade test, not just unit tests

  • Wrote a test plan of 16 on-demand classic workflows that together exercise all 79 activities in the previously published version.
  • Scripted the test data, the workflow creation, and a runner that executes every workflow, collects each one's results, and cleans up.
  • Ran them on the old version for a baseline, upgraded in place, ran them again, and diffed the two runs automatically.
  • Added 354 automated unit and integration tests alongside.

Fixed what the comparison found

The before-and-after diff exposed real differences that unit tests would not have caught. For example, six workflow argument names that existing workflows relied on had to be restored.

Made the build repeatable

  • A Power Platform build that leaves out activities whose tables don't exist there, built from the same source and keeping the original assembly name so existing installs upgrade in place.
  • Continuous integration that builds and tests every push, and a release workflow that builds the solution packages from a version tag.

The result

96activities in one deployable assembly
79old-version activities covered by the upgrade test
354automated tests
2builds, each managed and unmanaged

Every difference between the old and new version was found, listed in one report, and checked against a documented list of expected changes before release. Future changes can be verified by re-running the same automated test instead of clicking through workflows by hand.

Why it matters for you

This is the approach behind every Plugin Rescue engagement: inventory each component, record what it does today, upgrade it, and prove that nothing your business depends on has changed.