@microsoft.com

I am back.

It has been a while since my last post. About a month ago I started a new job as a Dynamics TSP (Technology Solution Professional) at Microsoft. It is a technical role aimed to support Dynamics related sales processes.
Sadly, It means giving up my MVP title, as Microsoft employees are not eligible for this award. 

This is a major change for me. In the last 8 years I was self employed of a sort, without a regular schedule, office or boss. Switching to work in one of the largest corporations on the planet is overwhelming. But in a good way. Although I am still drinking from the firehose, I can now access deep and broad layers of knowledge I was missing before.

I have been writing this blog since 2009 and plan to continue. Although I am a Microsoft employee now, the opinions and views stated in this blog are my own.

So now, armed with new knowledge and super powers, this blog is getting even better. Stay tuned. 

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

Get (Online) Ready

If your Microsoft Dynamics CRM organization is deployed on-premise and Online is not even a remote option, stop reading now, this post not for you. Or is it?

Most of my clients are enterprise level organizations with Microsoft Dynamics CRM deployed on-premise. But even in these organizations, Online is no longer a theoretic concept. Sooner or later, Online is coming…oh wait. it’s here.

Following are some tips which implemented today may render your migration to Online a bit easier in the future, but will probably make your life easier even while on-premise.

1. Keep it supported
There is an infinite number of unsupported customization methods and even more available for an on-premise deployment: direct database access, using database triggers, editing ASPX and CSS files, adding HTTP modules…the list goes on.
If you currently implement any of the methods mentioned above, start planning to replace it with a supported customization method, since these are not viable in Online deployment.

2. Get Sandboxed
Although on-premise you can register Plug-in and Custom Workflow Activities DLLs in full trust, I suggest registering these components to Sandbox mode.
In Online deployment, Plug-in and Custom Workflow Activities DLLs can only execute in sandbox, but even on-premise you can benefit from the sandbox isolation in security and performance aspects.
If you have code that exceeds sandbox limitations (file system/database access etc.), consider moving it to a different component such as an external Web Service.

3. Solution contained
Whenever possible, prefer a solution aware component rather than an external component. HTML (JavaScript, Images etc.) Web Resource over an external ASPX page, Action over a WCF/ASMX service. This will simplify your deployment process considerably even when moving a version between your on-premise test and production environments

4. Go Client
Whenever possible, prefer client side business logic over server side. Implementing business logic using JavaScript rather than Plug-in/Synchronous Workflow will yield better UX and reduce maintenance efforts in any deployment type:

  • There is a plethora of free utility JS libraries that can simplify and expedite your business logic implementation
  • JavaScript code does not require re-compilation
  • Debugging JavaScript code does not require in external tool (the browser developer tools will suffice)

Note that in Online deployment you can’t debug Plug-in/CWA components with the Attach To Process technique as server processes are not exposed.

5. Use modern APIs
Upgrade existing code to use the latest Microsoft Dynamics CRM APIs and end points. These APIs will last longer along with your business logic code and probably have performance and maintenance benefits.
When Online, old APIs and end points have higher probability to be decommissioned whether you like it or not.

6. Exposable Integration points
Integrating Microsoft Dynamics CRM with external on-premise applications is common in enterprise level applications.
Assuming some of these external applications will remain on-premise, make sure the integration points can be exposed directly or indirectly to Microsoft Dynamics CRM Online and vice versa in a secured and simple manner. Integrating an external application via a Web Service is preferred over consuming database stored procedures.

Accessing Form Header Web Resource

Although this Help article states that with Microsoft Dynamics CRM 2016/Online “You can’t include a web resource in a form header or footer”, you certainly can.

Sadly, form Footer Web Resource no longer display any content (as it did in version 2015). Form header displays content correctly, but adding it will spread the header fields all over the form width.

adding web resource will spread the header fields all over the form width

If you are ok with the UI, you might want to access the header Web Resource programmatically via JavaScript. Maybe when a form attribute value changes, the Web Resource content should change dynamically.
Unlike header attributes, which can be accessed using
  Xrm.Page.getControl(“header_name”), the header Web Resource can not be accessed this way as it seem to be invisible to the getControl function.

So how can the header Web Resource ‘Listen’ to form and field events?

Since Web Resource can access the Xrm.Page object via the parent object, it has full access to the form elements and events. The addOnChange function allows the the Web Resource code to register an internal function as an event handler for a form or field event.

The following sample demonstrates HTML Web Resource located in the Account form header area, ‘listening’ to the Account Name attribute change event. 
The code is located in the HTML Web Resource:

//register event handler to the account name attribute onChange event

function registerRefreshEvent()
{
    if(parent.Xrm.Page != null)
    {
         parent.Xrm.Page.data.entity.attributes.get(“name”).addOnChange(refreshContent);
    }
}

//do something with the Web Resource content…

function refreshContent()
{
    alert(“Refreshing Web Resource content…”);
}

registerRefreshEvent();

HTML Web Resource located in the Account form header area, ‘listening’ to the Account Name attribute change event

Update Records with the Import Wizard

I recently noticed that in version 2016, the option to export records for update (available in version 2015 as seen below) has vanished from the Export To Excel dialog.
When checked, this option allows you to update the exported data and later on use the Import Wizard tool to update existing records.

option to export records for update available in version 2015

import existing records with the Import Wizard

Consulting Faridun Kadir, a fellow MVP, I learned that exporting MSCRM records to a static worksheet exports records GUID (record unique identifier) by default as a hidden column. This GUID is later used by the Import Wizard mechanism to determine if the imported record is to be created or updated.
For this reason, the ‘Make this data available for re-importing’ checkbox was removed from the Export to Excel dialog.

image
 
As you can see above, the hidden columns title includes a warning (‘DO Not Modify’). Indeed, changing these columns data will end with an import failure. So although exposing these columns by itself will not cause any harm, you better leave it hidden to prevent an accidental change.

All you have to do in order to update existing records is to update required value in the Excel file and import via the Import Wizard. You can also add new records which will be created in the same import job.

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.