Entity Scope Business Rules demystified

Entity scoped Business Rules run on both client and server side. On the server side, Business Rules are executed synchronously when a record is saved (created or updated) and this means that in some cases, Business Rules can replace synchronous Plug-ins. Business Rules UX is better and maintenance wise, implementing business logic using the declarative Business Rule is preferred over Plug-in custom code.  

Sounds great, but for some Business Rule actions the meaning of running on the server side is a bit obscure:

  1. Show error message: on client side, the save operation is prevented by the error message. Is the save operation also blocked on the server side? Does the caller receive the designated error message?
  2. Set business required: does the save operation fail if a value is not supplied for the required field on server side?
  3. Lock or unlock field: does this action actually prevent setting field value on server side?

As for the other actions, I assume the Set visibility action is meaningless on server side and also that Set field/default value actions work on both client and server side in the same manner.

To test these three actions on the server side, I created and updated an Account record via the OrganizationService API in a synchronous manner while activating only the relevant Business Rule. Following are the various tests and results:

  1. Show error message

    Business Rule definition:

    Show error message action test 

    Client side test:

    Show error message action client test

    Server side test result: Account record is not created, the caller receives the designated error message

    Show error message action server test

  2. Set business required:

    Business Rule definition:

    Set business required action test

    Client side test:

    Set business required action client test

    Server side test result: Account record can not be created without specifying a value for required field

    Set business required action server test

  3. Lock or unlock field

    Business Rule definition:

    Lock or unlock field action test

    Client side test:

    Lock or unlock field action client test

    Server side test result: Account record is created successfully although the Account Number field is set to be locked by the Business Rule

    Lock or unlock field action server test

Conclusion: Show error message and Set business required actions perform on server side similar to a Plug-in. The Lock or unlock field action is meaningless on server side.

Rollup Field vs. Security Role

One of the professional benefits I gain from training Microsoft Dynamics CRM courses appears from time to time in the form of an innocent question from a student. A question which makes me stop for a moment and think… What would Mr. Spock answer to this?

Here is one: Does a Rollup field calculation take the user’s privileges into account?

Let me demonstrate: a user has access to a Project record which contains the Total hours consumed. This is a Rollup field which sums up the related Activity Report records Total Hours field value. The user Security Roles prevent him for reading any Activity Report records.
Having this, when the user activates the Total hours consumed field on demand calculation functionality,  would the result be zero?

Humm… on one hand, It seems logical to expect that if the user has no access to the data used for calculation, he will get partial or no calculation result. On the other hand, displaying partial or no result can lead the user to the wrong business decision.

What would Mr. Spock answer to this?
After testing this scenario I can answer that Rollup field calculation ignores the user’s privileges. Even without access, the Activity Reports entity, a user can activate a Rollup field on demand calculation and get a result as if he had full privileges.

The reason for this is that Rollup fields calculation is performed under the privileges of the System user account rather than the actual operating user. If you want to prevent read access to calculation result, use Field Level Security as Microsoft suggests in this article.

Rollup field Supporting sample

Entity JavaScript Scaffold

In the last couple of years I have been writing more JavaScript code than Server side code in my Microsoft Dynamics CRM projects. Better UX, plethora of supporting JavaScript libraries, easier deployment and maintenance made me prefer client side solutions.

I usually create a JavaScript library for each entity requiring client side functionality (forms, command bars etc.).
Over time, I have formed a JavaScript class scaffold. As this scaffold has improved my productivity when it comes to developing, debugging and maintaining client side code, I would like to share it here.

Consistently using this or any other scaffold, especially in large teams/projects, can significantly lower the cost of maintenance as developers quickly learn to find the right location for new code or debugging breakpoint, even in code they have never seen before.

A few key concepts implemented by this scaffold:

  1. Using Namespace

    Using namespace help avoiding collisions with other functions or variables in the global namespace. External solutions may contain code which is beyond your control and so it is important to protect your code from collisions that can be hard to detect and debug.
    Using namespace also allow encapsulating private functions and variables while exposing public elements.

    image

    In this example, I am using ContactServices as my namespace. Consuming any public function from this class (e.g. form onLoad event handler) will use the namespace as prefix: ContactServices.HandleFormLoadEvent.
    The ns alias is used to attach public functions to the namespace.

  2. ‘Constants’ management
    Managing strings and magic numbers in a designated container lowers maintenance efforts as it eliminates the need to search for these values all over the code when a change is required.
    The const keyword can be used, but I am not sure it is supported by all browsers.

    image

  3. Generic event handlers
    The scaffold generic event handlers match the entity form events. I like to think of these as managing functions which doesn’t perform actual work (like any good manager) but activates the relevant worker functions.

    The ns prefix exposes the generic event handler as ‘public’  functions which can be wired to the form /attribute events.
    In my sample here, I would use ContactServices.HandleControlChangeEvent to launch the generic onChange event handler. Note that some of these generic event handler require context, so either check this in the event definition form or extract with code if not supplied by caller.

    Why should you use generic event handlers?
    Attaching event handlers via form is simplified since the event handling function name never changes.
    This is especially useful with attributes onChange event which is usually wired directly to event handling function.
    The following generic event handler extract the initiating attribute name from the context and use it to direct the event to the actual handler. This way, all onChange event handlers can be managed in one known location.
    The generic event handler also handles exceptions and frees the actual event handlers from this task.  This way, no exception can escape your catch block.

    image

  4. Public/Private elements
    Private variables and functions are used inside the namespace scope and are not exposed to external consumers.
    This allows exposing just the API you intend to and simplify matters for external consumers.
    Functions and variables which are prefixed with ns are exposed outside the namespace, other are invisible.
    To access a ‘public’ variable inside the namespace code, use this keyword.

    image

The full JavaScript scaffold code can be download here.
The scaffold is not wired to any specific Microsoft Dynamics CRM version. These concepts can be applied down to 2011 version at least.

If you have any comments or improvements for this scaffold, I would like to hear about it.  Share it here.

Field Level Security – Update, Don’t Read

I always assumed Field Level Security privileges are somehow inclusive, meaning you can’t have Update privilege without Read. I was wrong.

Defining the Field Security privileges like this

image

will prevent the profile users from reading the secured field value but will allow them to create with and update it.

FLSDemo

I can’t think of a business process which requires such behavior, but since Field Level Security apply to APIs as well as UI, it may be useful when external applications are required to update a secured value but are not allowed to retrieve it.

Plug-in Configuration Manager Utility

Plug-in components often require external configuration settings. Maybe the Plug-in code consumes a web service which end point alternates between test and production environments or maybe you use the Plug-in configuration to turn logging on and off. Basically, any code setting which depend upon external resources is worth exporting to external configuration as it may prevent code re-compilation, additional testing etc.

There are some common approaches to implement configuration settings for Plug-in components:

  1. Configuration file: each Plug-in instance consumes a configuration file
  2. Configuration record: each Plug-in instance executes a query to retrieve a designated Microsoft Dynamics CRM configuration record
  3. Step configuration: each Plug-in instance constructor receives configuration settings from the Step secure/unsecure configuration

Performance wise, option 3 is preferred as the Step’s secure/unsecure configuration is cached alongside the Plug-in step and no additional operation is required to retrieve it. Changing the Step’s secure/unsecure configuration will automatically un-cache and reload relevant Plug-in with updated configuration. If you are not familiar with this option implementation, read this.
Options 1 and 2 require an expensive IO operation or query as each Plug-in instance explicitly consumes additional resources to retrieve configuration settings. When one of these approaches are applied in large scale (or with poor server resources), it will take a considerable toll on server performance and sometimes, the UX.

While option 3 yields better performance, it is not maintenance friendly. In enterprise scale applications, you may have to go through hundreds of Plug-in steps to update secure/unsecure configuration settings. Now think about doing this while deploying a version to the Production environment a 3 AM.

In this post, I offer a utility which allows you to enjoy Step configuration performance benefit along with simple maintenance for configuration bound Plug-in components.

WIIFM?

An unmanaged solution can be downloaded here. Use this tool as is or change the code to better suit you needs.
Although this tool was designed and built for Microsoft Dynamics CRM 2016 (Online/On-premise), the approach behind it can be implemented with previous versions, probably down to 2011.

As displayed below, the Plug-in Configuration Utility allows you select a registered Plug-in assembly, view related Steps and finally view each Step configuration details.
Clicking the ‘Update Configuration’ while a single or multiple Steps are selected will updated the respective configuration settings.

By default, Custom Work Flow Activities and System owned Plug-in assemblies are hidden, but can be revealed by unchecking the matching checkbox. You can view some interesting configuration settings under the Microsoft.Crm.ObjectModel assembly Steps, which are hidden when using the Plugin Registration Tool.
Although possible, do not change any configuration settings for these Steps.

Plugin Configuration Manager Demo

Bits & Bytes

The entities used behind the scenes here are

  1. pluginAssembly – representing registered Plug-in DLL file
  2. pluginType – representing IPlugin event handler class contained in the Plug-in DLL file
  3. sdkMessageProcessingStep – representing Step details binding the plugintype event handler to specific entity and message. Contains the unsecure configuration string
  4. sdkMessageProcessingStepSecureConfig – representing a secure configuration record related to the sdkmessageprocessingstep. Contains the secure configuration string

Plugin Configruation Entity Model

Although the Plug-in Registration Tool displays the secure configuration string as part of the Step settings (represented by the sdkMessageProcessingStep entity), this attribute actually resides in the related sdkMessageProcessingStepSecureConfig entity. Moving the secure configuration string to a different entity allows setting different privileges, as the secure configuration string may contain sensitive data like password.

This also means the in order to programmatically set new secure configuration string for a Step, it is required to create and relate a new sdkMessageProcessingStepSecureConfig  record.

Plugin Step Secure Configruation Privileges

Dude, Where’s My Workflow?

There is no built view in Microsoft Dynamics CRM that shows the different solutions to which a component (such as Workflow Rule) is related. If you have many solutions, iterating through all of them can be exhausting and time consuming.

The following query retrieve all solution which contain a Workflow Rule named testwf:

<fetch version=”1.0″ mapping=”logical”>
    <entity name=”solution”>
        <attribute name=”friendlyname”></attribute>
        <link-entity name=”solutioncomponent” from=”solutionid” to=”solutionid” >         
            <link-entity name=”workflow” from=”workflowid” to=”objectid”>
                <filter>
                    <condition attribute=”name” operator=”eq” value=”testwf“></condition>      
                </filter>                       
            </link-entity>
        </link-entity>    
    </entity>
</fetch>

The solutioncomponent entity binds elements such as Workflow Rule to Solutions. The solutionid attribute maps each solutioncomponent record to a Solution record and the objectid attrbiute maps to the Workflow Rule. Off course, you can find any solution element with a similar query, just change the relationship attribute.

Here is the query result which includes two solutions:

[
  {
    "formattedValues": {},
    "friendlyname": "Default Solution",
    "solutionid": "fd140aaf-4df4-11dd-bd17-0019b9312238"
  },
  {
    "formattedValues": {},
    "friendlyname": "Web API Samples",
    "solutionid": "1c35faf2-ee8c-4a1c-a838-d49692d0d941"
  }
]

You can use various tools to run FetchXML queries, I am using XRMToolBox.