Skip to content

Tag: Dynamics 365

Missing privilege for editable grids

Posted in Dynamics 365, Power Platform, and Revive

In one of our last projects we used an editable grid from Microsoft, but had a strange issue.
Read here how we detected and identified a missing privilege for editable grids.

Issue

During testing with an user account we found that the editable grid for a custom entity does not render. For admins is all fine.
This is how it should look.

This what it actually was.

Analysis

First thing we’ve checked was whether someone has changed the form rendering mode because editable subgrids don’t work on legacy forms. But it was still correct set.

Also we checked the known editable grids limitations for fields from related entities, the state field, partylists, customer and composite fields. But there was no such field in the view.

Further we’ve checked the users security roles. They have a custom role, but it includes all privileges for the parent and child entity.

Next we proved what happens when we remove the editable grid control and use the read only version instead. As a result, everything was ok in the read only grid.

Now I had a look at the browser console and found an error . . . a few times.

As desperation act we gave the user the default sales person security role and were surprised that now everything worked fine.

Identify the missing privilege for editable grids

We compared the two security roles and identified the “prvReadRole” as origin of the issue.
It was set to “None Selected”. I assume it is needed by the editable grid control the check if the user has all necessary privileges to edit the records in his security roles.

CRM background color

Posted in Dynamics 365, Power Platform, and Revive

With Dynamics CRM 2015 Update 1 Microsoft introduced the possibility to create own themes. In this post I won’t show you default settings and screenshots of unicorn colored CRM systems, I will show you the hidden setting for the CRM background color.

When you query the properties of a theme you will discover a setting that isn’t visible on the theme record (the highlighted line).
Please spare yourself the trail to customize the theme formular, it is not possible.

{
   "name": "CRM Default Theme",
   "isdefaulttheme": false,
   "logotooltip": "Microsoft Dynamics 365",
   "_logoid_value": null,
   "navbarbackgroundcolor": "#000000",
   "navbarshelfcolor": "#DFE2E8",
   "headercolor": "#1160B7",
   "globallinkcolor": "#1160B7",
   "selectedlinkeffect": "#B1D6F0",
   "hoverlinkeffect": "#D7EBF9",
   "processcontrolcolor": "#D24726",
   "defaultentitycolor": "#001CA5",
   "defaultcustomentitycolor": "#006551",
   "controlborder": "#CCCCCC",
   "controlshade": "#F3F1F1",
   "backgroundcolor": "#FFFFFF",
}

So I had the idea to update the value directly through a web service call and it works.
After publishing the theme, I had a new CRM background color.

What you need to know is that Microsoft changes value back to the original CRM background color (#FFFFFF), every time you save the record through th UI.

The CRM background color bookmarklet

Since I’m a lazy guy who likes it when things are reusable, I’ve created the following bookmarklet.

Drag and drop the “CRM background color” button on your bookmark toolbar.
 

With the bookmarklet your process to change the CRM background color is:

  1. Open your theme record
  2. Make your customizations
  3. Save the theme
  4. Use the bookmarklet
  5. Publish your theme

I’m not sure if Microsoft will support it.
From a technical point of view is it only an update of a record through the webservice. Considered a manufacturers point of view, they don’t want that we can change it – otherwise we had probably an option for it in the UI.

Happy styling!

Export a solution via Javascript

Posted in Dynamics 365, Power Platform, and Revive

Last week I got an error during a solution export, but the error message wasn’t very helpfull. I then had the idea to export the solution via Javascript with the hope to get an more meanfull error.
Fortunately it was so and by the way I’ve learned how to export a solution via Javascript.

//Just to make the selection oh the target version easier
var targetVersions = {
    v_7_0 : "7.0.0.0",
    v_7_1 : "7.1.0.0",
    v_8_0 : "8.0.0.0",
    v_8_1 : "8.1.0.0",
    v_8_2 : "8.2.0.0",
};

function exportSolution(strSolutionName, asManaged, strTargetVersion, objParameter)
{
    var parameters = {
        SolutionName: strSolutionName,
        Managed: asManaged,
        TargetVersion: strTargetVersion,
        ExportAutoNumberingSettings: objParameter.ExportAutoNumberingSettings || false,
        ExportCalendarSettings: objParameter.ExportCalendarSettings || false,
        ExportCustomizationSettings: objParameter.ExportCustomizationSettings || false,
        ExportEmailTrackingSettings: objParameter.ExportEmailTrackingSettings || false,
        ExportGeneralSettings: objParameter.ExportGeneralSettings || false,
        ExportMarketingSettings: objParameter.ExportMarketingSettings || false,
        ExportOutlookSynchronizationSettings: objParameter.ExportOutlookSynchronizationSettings || false,
        ExportRelationshipRoles: objParameter.ExportRelationshipRoles || false,
        ExportIsvConfig: objParameter.ExportIsvConfig || false,
        ExportSales: objParameter.ExportSales || false,
        ExportExternalApplications: objParameter.ExportExternalApplications || false,
    };

	var req = new XMLHttpRequest();
	req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v8.0/ExportSolution", true);
	req.setRequestHeader("OData-Version", "4.0");
	req.setRequestHeader("OData-MaxVersion", "4.0");
	req.setRequestHeader("Accept", "application/json");
	req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
	req.onreadystatechange = function ()
	{
		if (this.readyState === 4)
		{
			req.onreadystatechange = null;
			if (this.status === 200)
			{
                //you will get a download notification
			}
			else
			{
				Xrm.Utility.alertDialog(this.statusText);
			}
		}
	};
	req.send(JSON.stringify(parameters));
}

How to load Javascript from a webresource

Posted in Dynamics 365, Power Platform, and Revive

Imagine an usecase where you can dynamically load a Javascript from the CRM webresources because it doesn’t need to be loaded on every single form load. Perhaps a polyfill to add missing browser functions or a Javascript library like jQuery. Here it is…

function loadJavascriptFromWebresource(strWebresourceName, async)
{
    //sync or async (default)
    if (async == undefined) { var async = true; }

    //build a new webrequest to get the content of the webresource by its name
    var req = new XMLHttpRequest();
    req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.0/webresourceset?" +
        "$select=content&$filter=name eq '" + strWebresourceName + "'", async);
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.onreadystatechange = function ()
    {
        if (this.readyState === 4)
        {
            req.onreadystatechange = null;
            if (this.status === 200)
            {
                //get the result of the request
                var result = (JSON.parse(this.response)).value[0].content;

                //decode the base64 encoded result
                var script = atob(result);

                //make an indirect eval call to make it globally available
                window.eval(script);
            }
            else
            {
                Xrm.Utility.alertDialog(this.statusText);
            }
        }
    };
    req.send();
}

My personal usecase was to add a promises polyfill to the Internet Explorer. So, if you combine this post, my post about “Internet Explorer and promises” and you have a promises polyfill in your CRM webresources, you can use promises and do only load the polyfill in case the browser doesn’t support it.

Empty pipelinephase on opportunity quickcreate

Posted in Dynamics 365, Power Platform, and Revive

You all know the most common usage of the pipelinephase field of an opportunity. It’s the sales funnel chart in sales dashboards.
By default the pipelinephase field is filled with the number of the current business process, followed by its name. But sometimes it stays empty. You can imagine how unhappy the sales guys are about that.

What I found out

It depends on how you create the opportunity. If you create an opportunity through the quickcreate feature, where it does not matter if you use the global “+” sign or the contextual “+” sign of a subgrid to create it, the pipelinephase field will not be filled until you step further in the next phase.

Workaround

Build an asynchronous workflow on opportunities that is triggered on create and fills the pipelinephase field if it is empty.

Below you find a solution to download that contains this workflow. It takes dynamically the phase name of the current business process. It is also an ondemand workflow, so that you can run from a view or advanced find that shows you all open opportunities with an empty pipelinephase field.

Issue reporting

There is already an proposal on CRM-Ideas for this issue. You can find it H E R E. It is already 9 month old and has only 4 votes. My appeal to you, follow the link, sign in and vote for it. The more votes it get, the higher is the attention from Microsoft.