Dynamics 365/CRM customizations inflicted by a customer are always fun. How can I tell their customizations apart? Easy, by the new_ prefix. Where things get really complicated if the customer later asks you to do something they are not sure how to.
Just recently I was asked to stop couple fields from being locked if the user has one of the preconfigured roles. The challenge was that those fields were locked as a result of elaborate concoction of business rules, the business rules cannot be selectively applied by role and there is no condition in the business rules that would allow role filtering. Sigh.
Option 1
Duplicate the form, scope the business rules to the original form only and grant form access only to the selected roles. It will kind of work but maintenance of multiple forms is no fun and I bet I would have been asked to automatically switch the forms.
Option 2
Rewrite rules as javascript. No, thanks, I choose life.
Option 3
Add straightforward script executing onLoad and onChange unlocking those fields for the selected roles. That sounds good. Sleeves rolled up, script written, wired in, and … no worky. Because, even though there is no definite documentation on the order of the execution, business rules tend to get in last, after all the custom event handlers have been accounted for.
The workaround is surprisingly simple. Javascript, as implemented by all browsers, is event-driven but single-threaded. That means if we create an event around our function, it will push the call into the queue behind all those pesky business rules scripts.
function doUnlockControls(fc) { fc.getControl("new_foo").setDisabled(false); fc.getControl("new_bar").setDisabled(false); } function unlockControls(fc) { if(userHasAnyRole(['Role 1', 'Role 2']) { setTimeout(doUnlockControls, 0, fc); } } function OnLoadAndOnChanged(execContext) { var formContext = execContext.getFormContext(); unlockControls(formContext); }
setTimeout function creates an event that gets pushed to the queue and executed after the business rules scripts, even with the timeout set to zero. So this workaround works if you have some code that you have to execute after the business rules. But, as with any unsupported workaround, use at your own risk, contains small parts, choking hazard, swim between the flags. Not tested on animals, children or CRM.
(Facebook and Twitter cover photo by Melanie Pongratz on Unsplash)
Sorry, but this is something I would never recommend.
We made the decision for our projects that we use business rules only if their is no need for scripting. As soon as we need scripting because of the requirements we replace the business rules by scripting as well. Otherwise you end up in scenarios you described above, nightmare in support.
Additionally I recommend not to use security role names for business logic. What happens, if an additional security role is required? Do you really want to touch the code again?
Hey Lars,
appreciate the thought. I don’t believe that there is a word “recommend” anywhere in the tip. In fact, right at the bottom it says (highlight mine):
FWIW, I agree with you on all accounts. Mixing business rules and scripting is not a good idea. Relying on the role names is not a good idea. However, when working with a business, especially a small one, there is a need for a compromise between what the business wants, what the business needs, and what they are prepared to pay for. I can’t go around slapping business every time they decide to add a business rule. This tip is exactly that – a compromise, a band-aid solution that works in the interim. Of course, it’s our responsibility to inform business of the options, and of the consequences.
Let me write a tip about compromises we make 🙂
Cheers
George