There’s a mini web server in CRM!
Back in December, I attended a seminar at Microsoft titled Building Government Business Applications with Dynamics 365 and presented by Prosoft Systems Intl. Frank Grimberg was speaking on Actions in Dynamics 365 CE. I worked with Actions on a few projects, though not extensively, and I found them to be very useful. They were pretty handy for work that is a bit annoying in JavaScript, such as setting a record Status Reason (which is of course easier now with Web API). During his intro, Frank made a comment about Actions acting like a mini web server built right in CRM and that struck a cord. What Frank described was invoking an Action from a Web Resource, invoking some server side code via Custom Workflow Activities, and returning complex data such as JSON or XML through an outbound Process Argument.
Now that’s a cool idea! In earlier versions of CRM, I had seen some home grown methods of invoking “service calls” to CRM. For example, create a custom Entity and write some client side script to create a record that represents a “service call”. Plugins then fire to perform your server side work and save results into the new record. Once complete, your client script retrieves the data through an an additional retrieve request. A clever idea, but this is can turn into a significant amount of work to create and maintain. With Frank’s model, we can just call into an existing CRM Action and return our results via the output Process Argument, with all of the back end work handled by the Dynamics Framework.
Back to the drawing board!
At the time, I had been working on a custom user interface web resource that required several sequential calls to Web API endpoints. I had a lot of work on the client side to chain the calls and transform the data into a custom JSON format required for the client side components. While working on first iteration, I knew that I was not using the best method because chaining together several Web API calls is not the best user experience with time to load, and it is not the easiest model to unwind in the case of an error.
Taking Frank’s suggestion, I moved the logic for the multiple Web API calls and data transformation into a Custom Workflow Activity to be invoked from an Action by my web resource. This meant that all retrieve calls happened on the server, I could leverage C# code to do some additional manipulation instead of JavaScript, and I reduced the client side calls from many to one. I was also able to reduce the footprint of both the client side script and the JSON data by transforming it server side.
The end result is a much more manageable code base and more efficient processing for the overall component: No more monolithic client side code and a much more efficient way of passing around data.
Quick Example
So what does all this look like? It’s relatively straight forward. To illustrate the model, we can create a custom Action that includes an output Process Argument and test it using the CRM REST Builder by Jason Lattimer. If you have not used it, it’s an AMAZING tool for testing Web API calls. Without it, I would never be able to remember that syntax. Check it out the following link: CRMRESTBuilder on Github.
Action!
The sample Action is pretty simple: bound to no entity and has one input and one output Process Argument, MyName: string
and JSONOut: string
The action has just one step: set the value of the JSONOut Process Argument.
You can see that this is just taking the input Process Argument and adding it to a simple JSON structure when setting the value.
Call to Action!
Before you building out a full Web Resource, you can easily test the result of an Action by using the CRM REST Builder. Jason’s tool will build a JavaScript snippet that will invoke your Action as if it’s being called from a Web Resource.
Once the REST Builder loads, we can choose Action from the Action section, and from the new Action drop down, choose our custom Action to run. You can see that it has retrieved the Action metadata and presented us with the input Process Argument named MyName.
I added my name as the value for the input Process Argument and when we choose Create Request, we will have some automatically generated code to run. Before we execute, we want to make a few updates to the generated script so that we can view our results. The REST Builder tool allows you to make edits to the generated code before executing on the Code (Editor) tab. Here, we can use the ultimate debugging tool for JavaScript… alert()
!
Adding a few lines to Web API call response section of the code, we can view the resulting JSON from our new Action with a few alert statements.
And the ever powerful alert debugger output, you can see the results that we added to the response processing:
Below is the full JSON result returned in our output Process Argument.
{
"@odata.context":"https://XXXX.crm.dynamics.com/api/data/v8.2/$metadata#Microsoft.Dynamics.CRM.futz_ActionWebServerResponse",
"JSONOut":"[{\"myname\":\"Jim Novak\"}]"
}
In the script snippet, we retrieve the string value of the named Process Argument and parse it into one more time using the JSON object. Here we can see that the value passed via the input Process Argument was returned as part of the output, with James Novak
added as the value of the myname
JSON field.
[{ "myname":"Jim Novak" }]
Now that this is a parsed JSON object, you can apply additional client side rendering or processing logic required by your project.
Summing up
Obviously, this is a really REALLY simple example. The JSON is almost completely hard wired as part of the Action and we are using only a single input and output Process Arguments. But this model can easily be extended as I described earlier in the post. In my custom Activity, I invoke a Custom Workflow activity which does the heavy lifting and returns my JSON into the output Process Argument using the Assign step. So the only real difference between this simple example and my real world situation is the addition of the call to a Custom Workflow Activity and the return of more complex JSON as part of the output Process Argument. And keep in mind that because this is an Action, it’s sole function is not limited to building the JSON. You can add other Steps to your action to create or update records, send emails, start child workflows, etc.
Some concerns or caveats to this use of actions would be with time to execute and to the limits on the amount of data being returned. For example, the official documentation states:
Watch out for long running actions
If one of the steps in the action’s real-time workflow is a custom workflow activity, that custom workflow activity is executed inside the isolated sandbox run-time environment and will be subject to the two minute timeout limit, similar to how sandboxed plug-ins are managed. However, there are no restrictions on the amount of overall time the action itself can take. In addition, if an action participates in a transaction, where rollback is enabled, SQL Server timeouts will apply.
As for the limit on the string size of an output Process Argument, I have not been able to find a number. In my real world example, I am passing a decent amount of data via the JSON, but it’s not in the multiple megabytes that I have seen so far. So I have not really tested this threshold yet.
I would be interested to hear how others have leveraged Actions in a similar way and hit some limitations along the way.
A side note…
Looking for my notes on the event, I found an extensive MSDN article authored several years ago by Marc Schweigert and Andrew Schultz titled Dynamics CRM – Building Government Business Applications with Microsoft Dynamics CRM that cover many similar topics as the session hosted by Prosoft. Some of the topics are a bit outdated with new releases, but it’s still an excellent overview. Not surprisingly, Marc was a co-host of the December seminar and he presented a cool session about Microsoft’s DevOps solution. Check it out here: DevOps for Dynamics 365 Customer Engagement (CE) I’m going to be posting about it here soon.
And as always, comments, questions, and corrections are welcome!