Drag & Drop File Upload (part 1)

I have been planning to do this for over a year now, finally found the time. Started learning HTML5 (I recommend Pluralsight courses), and this is my first project.

In version 2016, Microsoft finally introduced some drag & drop file upload for the Word/Excel template feature, but that’s it. I would like to have similar UX in entity forms and Dashboards.

In this two-parts post, I’ll describe a working solution that allows users to upload a file by dragging it to a specific area in any business entity form or Dashboard.
The solution version available in this post adds an uploaded file as an attachment to a new Note record related to the context business entity. The next post version will use a more modular approach that can be used if you manage files outside of Microsoft Dynamics CRM database.


WIIFM?

An unmanaged solution can be downloaded here. Feel free to change the code to better suit you needs.

As this solution relies on HTML5 features, it will probably not work with early browsers versions. I tested it successfully with IE 11, Edge and Google Chrome v54.0.2840.71.
The solution uses the Web API service and therefore suitable for Microsoft Dynamics CRM 2016 Online and on-premise. For earlier MSCRM versions, some changes are required (read the Bits & Bytes section below)

Drag and Drop demo

Using the Solution

  1. Download, import and publish the Drag & Drop File Upload solution
  2. Add a Web Resource control to any business entity form
  3. In the Web Resource form, make sure the “Pass record object-type code…” option is checked
  4. Set the Web Resource format to span over 13 rows at least
  5. Map the Web Resource control to the dyn_DnDFileUploadArea.htm Web Resource
  6. Save & publish
  7. Drag n Drop like crazy

    image

Bits & Bytes

  • The solution code portion is contained in the dyn_DnDServices.js Web Resource
  • As the code uses Web API to create a Note record, it will not work with versions earlier than 2016. You can adapt the solution to earlier MSCRM versions by changing the createRecord function in the dyn_DnDServices.js Web Resource to use the OrgannizationData Service (REST) or the Organization Service (SOAP) to create a Note (Annotation) record
  • The code prevents uploading some file types (exe, js, etc.) according to the default blocked file extensions defined in the System Settings area. Maximum uploaded file size is also limited. Both settings are managed as constants and can be easily changed

    Managing blocked files extentions and file size settings   

  • I considered retrieving the blocked file extensions from the server instead of managing as constant. I opted for constants as I rather have better performance all year round over minor maintenance effort required once a year or maybe never 
  • You can can position the dyn_DnDFileUploadArea.htm Web Resource in a Dashboard. It will create Note record along with file attachment but will not relate it to any business record
  • Unfortunately, there is no supported manner to refresh the native Notes control. It would have been useful to automatically display the latest note after uploading a file

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.

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

MSCRM 2016 Admin Utility – Personal Views Manager

You may have noticed that even under the almighty System Administrator Security Role, you can’t view (nor edit, share, assign or delete) other users Personal Views. Well, that’s what personal means. Via the application UI, only the view owner can manage it.

This restriction can be troubling in some scenarios:

  • A user who shared his Personal Views with other users or teams has left the organization and now no one can edit or delete these views which are irrelevant or just annoying
  • A user has defined and shared a resources hungry Personal View which execution make the application grind to a halt

In this post, I’ll demonstrate a utility which allows you manage other users Personal Views, as long as you have the right privilege.

WIIFM? 

As you can see below, after selecting a user, you can view and manage the user owned Personal Views by deleting or assigning to yourself:

Personal Views Manager demo

If you are not into JavaScript coding and just want to use this utility, you can download the unmanaged solution. After importing this solution, open it, navigate to the Configuration element and manage away. It is recommended that you have the System Administrator Security Role. 

Note
that this utility was developed and exported from Microsoft Dynamics CRM Online Organization (v2016) but it should work perfectly in an on-premise v2016 deployment.
If you are using an earlier version (2015 and below), this solution is not for you, as it uses v2016 new API. There are similar solutions available for earlier versions.

Curious about the implementation details? read on. 

Bits & Bytes

Major implementation notes:

  • Although this utility can be easily implemented on the server side, I opted for client side & Web API which requires less code lines to write and is easier to maintain
  • I intended to add an option to Share Personal Views but encountered Web API limitation, as the GrantAccess message is yet unsupported. One option to implement this feature is calling a Custom Action wrapping a Custom Workflow Activity to execute GrantAccess request
  • The entity used to represent a Personal View is userquery 
  • The magic feature enabling access to userquery records owned by other users is Web API impersonation
  • In order to use impersonation with MSCRM (client or server side), the executing user (consuming the Web Resource) must have the prvActOnBehalfOfAnotherUser privilege, which is granted by default by the built-in Delegate and System Administrator Security Roles:

    prvActOnBehalfOfAnotherUser privilege 

  • To execute code using impersonation, the MSCRMCallerID header must be added to XMLHTTPRequest along with the impersonated user id:

    using the MSCRMCallerID header

  • Some good news though: in order to Assign a record using Web API, you only have to update the onwerid attribute. Sound so trivial…why did we ever need AssignRequest?

    use update instead of AssignRequest

Customization Aware Web Resource – Part 1

Web Resource is one of the most powerful and versatile extension mechanism in Microsoft Dynamics CRM. It supplies an open canvas to draw custom UI, business logic and whole applications within entity forms, dashboards and stand alone pages.
Coupled with the plethora of  free JavaScript libraries out there, you can easily provide your users with advanced solutions that work with Microsoft Dynamics CRM Data. In that sense, Web Resource can implement a custom client which can also be embedded into MSCRM elements.

One concern regarding the investment in Web Resource development is the loss of dynamic customization capabilities, which is MSCRM most prominent feature. Indeed, there is a price to pay when stepping outside Microsoft Dynamics CRM native clients.
The Customization Aware Web Resource approach can somewhat compensate as it suggests that whenever possible, attributes of elements within a Web Resource (mostly HTML & JavaScript) will be coupled with relevant customization features. So customizing entity field attributes like display name, description, requirement level, OptionsSet options etc. will be automatically reflected in your Customization Aware Web Resource.

Technically, this can be achieved by using the metadata querying capabilities of the OrganizationService or the Web API services.
Off course, this approach is relevant to any custom client, not just Web Resources.

One issue to consider when using the Customization Aware Web Resource approach is performance. While the OrganizationService.svc allows querying multiple entities & attributes with one query, the Web API service can only query one attribute at a time, so multiple queries may be required. Metadata queries are considered expensive, so if you plan to rely heavily on this approach, you should cache metadata queries results along with some cache invalidation mechanism.

In the following post, I’ll demonstrate a possible implementation of this approach. Stay tuned

Web API: Executing Custom Action via JavaScript

The Custom Action is an important tool in Microsoft Dynamics CRM architect belt. Here are some of the Custom Action key features:

  1. It can be called from both client & server side, enabling the SPoI approach (Implement once, consume anywhere)
  2. Supply a flexible, declarative business logic definition mechanism which can be called from other Processes as well as from custom code (unlike Plug-in)
  3. Can be extended with Custom Workflow Activities
  4. Can receive input parameters and return output parameters in a straight forward manner, similar to an Organization level Web Service

Why would you want to execute a Custom Action (which is a server side mechanism) via JavaScript? Here are some excellent reasons:

  • Provide an improved UX, as Custom Action can be executed a-synchronously from entity forms, web resources and Ribbon/Command Bar controls without blocking the user UI
  • You can bind server side logic to client side events, e.g. calling a Custom Action from an onChange or onSave event handlers
  • Implement a chunky rather than chatty communication with the server, as Custom Action usually wraps multiple operations which otherwise require multiple API commands

You can execute a Custom Action via JavaScript using raw SOAP (not recommended) or better yet, using the Sdk.Soap.js library (still SOAP, but nicely wrapped).
With Microsoft Dynamics CRM 2016 Web API you can now execute a Custom Action in the most simple manner, which is demonstrated in the rest of this post.

You can download an unmanaged Solution containing the sample Action and JavaScript code. This solution is for demonstration purposes only, please do not install on production or other critical environments.

  1. Define and activate a Custom Action in MSCRM 2016 Organization

    My sample Action receives few parameters, creates a Lead record and returns the new record URL.
    Note that this Action is defined for a global context. Also note the Action’s unique name and parameters names which are used in the following code.

    Define Custom Action

  2. Write JavaScript code to consume your Action

    The handleWebLead function defines the dyn_HandleWebLead Action name and parameters.
    It than calls the generic activateCustomAction function to execute the Action and return the output result.

    Define calling function
     
    The Action is executed using XMLHttpRequest which is defined to execute synchronously.

    Define Action executing function