Building Better Commands in D365: JS + Actions + Power Automate

In my previous post, I discussed a silent failure scenario involving a JavaScript-triggered Action + Plugin setup. This post explores a more structured approach using JavaScript + Action + Plugin, and how to scale it with Power Automate. Architecture Overview This approach separates responsibilities cleanly between: Client: JavaScript Logic: Plugins Integrations: Power Automate Step 1: JavaScript as the Initiator We start with a JavaScript function that triggers a bound action, keeping the UI lightweight and offloading processing to the server. Xrm.WebApi.online.execute({ entityName: "quote", entityId: quoteId, actionName: "new_CustomWinQuoteAction" }); Step 2: Custom Action as a Dispatcher The Custom Action serves as a reusable interface layer that: Accepts input parameters Supports versioning and audit Can be triggered from JavaScript, Power Automate, or other Plugins Step 3: Plugin for Business Logic A plugin is registered on the Custom Action step to handle the core business logic. public void Execute(IServiceProvider serviceProvider) In this method, you retrieve the context and execute operations like cloning records, creating tasks, or updating fields. This ensures critical logic stays within the Dynamics 365 execution context. Step 4: Power Automate for Scalability For operations involving delays, external APIs, or heavy workloads, we offload tasks to Power Automate. Common trigger methods include: HTTP request from the Plugin Azure Service Bus message Custom API endpoint Ideal use cases: Sending emails or Teams notifications Interacting with third-party services Logging or telemetry Plugin vs Power Automate Comparison Aspect Plugin (C#) Power Automate Execution Fast, synchronous Asynchronous CRM Context Full access Limited context and impersonation control Integration Complex setup Easy third-party integration Use Case Secure, governed, critical logic Non-critical, long-running tasks Real Example: Clone and Notify Pattern JavaScript triggers the CloneAndNotifyAction. The Custom Action receives the Opportunity ID. A Plugin: Clones the Opportunity Creates follow-up tasks Sends an HTTP payload to Power Automate Power Automate: Sends notification emails Logs the operation in SharePoint Conclusion This layered pattern enables you to: Separate logic between frontend, backend, and external services Reuse business logic across multiple entry points Scale with Power Automate without overloading Plugins If you're designing custom commands or ribbon buttons in Dynamics 365, this approach ensures flexibility, testability, and long-term maintainability.

May 5, 2025 - 14:25
 0
Building Better Commands in D365: JS + Actions + Power Automate

In my previous post, I discussed a silent failure scenario involving a JavaScript-triggered Action + Plugin setup. This post explores a more structured approach using JavaScript + Action + Plugin, and how to scale it with Power Automate.

Architecture Overview

This approach separates responsibilities cleanly between:

  • Client: JavaScript
  • Logic: Plugins
  • Integrations: Power Automate

Step 1: JavaScript as the Initiator

We start with a JavaScript function that triggers a bound action, keeping the UI lightweight and offloading processing to the server.

Xrm.WebApi.online.execute({
  entityName: "quote",
  entityId: quoteId,
  actionName: "new_CustomWinQuoteAction"
});

Step 2: Custom Action as a Dispatcher

The Custom Action serves as a reusable interface layer that:

  • Accepts input parameters
  • Supports versioning and audit
  • Can be triggered from JavaScript, Power Automate, or other Plugins

Step 3: Plugin for Business Logic

A plugin is registered on the Custom Action step to handle the core business logic.

public void Execute(IServiceProvider serviceProvider)

In this method, you retrieve the context and execute operations like cloning records, creating tasks, or updating fields. This ensures critical logic stays within the Dynamics 365 execution context.

Step 4: Power Automate for Scalability

For operations involving delays, external APIs, or heavy workloads, we offload tasks to Power Automate. Common trigger methods include:

  • HTTP request from the Plugin
  • Azure Service Bus message
  • Custom API endpoint

Ideal use cases:

  • Sending emails or Teams notifications
  • Interacting with third-party services
  • Logging or telemetry

Plugin vs Power Automate Comparison

Aspect Plugin (C#) Power Automate
Execution Fast, synchronous Asynchronous
CRM Context Full access Limited context and impersonation control
Integration Complex setup Easy third-party integration
Use Case Secure, governed, critical logic Non-critical, long-running tasks

Real Example: Clone and Notify Pattern

  1. JavaScript triggers the CloneAndNotifyAction.
  2. The Custom Action receives the Opportunity ID.
  3. A Plugin:
    • Clones the Opportunity
    • Creates follow-up tasks
    • Sends an HTTP payload to Power Automate
  4. Power Automate:
    • Sends notification emails
    • Logs the operation in SharePoint

Conclusion

This layered pattern enables you to:

  • Separate logic between frontend, backend, and external services
  • Reuse business logic across multiple entry points
  • Scale with Power Automate without overloading Plugins

If you're designing custom commands or ribbon buttons in Dynamics 365, this approach ensures flexibility, testability, and long-term maintainability.