Wednesday, 27 February 2019

Alert and Confirm syntax will not work for Dynamics 365 App For Outlook

Recently, I just helped customer to upgrade their system to 9.1.x.x
We encountered many issues. However, the issue that I want to bring up now is issue regarding to the App for Outlook

We found that there is custom ribbon that calls Custom Javascript and it does nothing, no error, nothing is so-called exception occurred because I did debugging and did place the try catch block.
Unlike using Web, the debugging in Outlook is not so easy.
After I did debugging with try catch, I found out that the script is actually running well and has no error.

So, the problem is: the script that is executed is pretty simple just do some validation and show alert when does not fulfill, then throw a confirmation dialog then save the form.
Yes, the script is sucessfully executed from start to the end.

Then, why the ribbon function is not running?



It is because the alert and confirm scripts are still using old ways:

alert("Please complete all mandatory fields before submitting the form")
if (!confirm("Are you sure that you want to submit this form??")) {
            return;


So, there is no error it is just not 'supported' and not 'translated' well in the App for Outlook.
yes, it does working in Web, but not in App for Outlook.

So, after I changed it to

 Xrm.Utility.alertDialog("Please complete all mandatory fields before submitting the form");
or
    var alertStrings = { confirmButtonLabel: "OK", text: "Please complete all mandatory fields before submitting the form" };
    var alertOptions = { height: 100, width: 500 };
    Xrm.Navigation.openAlertDialog(alertStrings, alertOptions);

and

if (!Xrm.Utility.confirmDialog("Are you sure that you want to submit this form??")) {
            return;
        }

It is working perfectly!
Example:








**The first one is still supported and it is intended for simple alert.
Xrm.Utility namespace may be obsolete for the Alert and Confirm Dialog, so as per MSDN recommendation, we need to change it :
https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/clientapi/reference/xrm-navigation/openalertdialog

https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/clientapi/reference/xrm-navigation/openconfirmdialog

https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/clientapi/reference/xrm-utility

Hope it helps!

Thanks




Wednesday, 23 January 2019

Be careful when you import managed solution and you modify that component

Hi all,

Just a short blog as per current experience.
I know it has been years I never write any post.

So, my current post is just want to explain that should you imported solution as Managed and then something requires you to update.
Does not matter it is just a display name for name, is searchable Advanced Find for a field, a Report Category for a Report, Web Resources modification directly from the Production with Managed solutions.

Please be noted that you are doing wrong thing and there is no way back for CRM Online other than raising ticket which can be rejected as it will make that component becomes 'Unmanaged' and is part of Active or you call it Default Solution.

Well, you can see it is still "Managed" in your Managed solution, but it is actually a Default Solution
It means, your component CANNOT Be DELETED anymore using Holding nor Solution Upgrade or manually you CANNOT Delete. It will remain there.

So, if you have fields you want to delete, dont hide it.
If you have report you want to hide dont hide it.
Dont do that directly in your Managed Solution environment.
Do it in the UNMANAGED Solution and you can use SOLUTION UPGRADE method to delete that component like people posted before.

This what happen the moment you changing something in your report:

The report you modified directly become "Unmanaged" and part of the "Default Solution" as the final layering. You WILL NOT be able to deploy the Managed solution again which has this component.
As there is conflict internally in the database.

So, dont do that.
Always stick in your Development for any modification.
If it is something like Report, sitemap that frequently changing and easy to maintain, it is still the best to keep it Unmanaged so you can modify and delete if you dont like it, all manually but possible.
Well, like entities, changing directly in PROD is not recommended.

Or, you can prevent the customizable


Hope this is useful.
Thanks

Wednesday, 15 February 2017

Error: "Unable to Login to Dynamics CRMOrganizationWebProxyClient is nullOrganizationWebProxyClient is nullOrganizationServiceProxy is nullOrganizationServiceProxy is null" during connecting to CRM Online using Xrm.Tooling.Connector

It’s been long time I have not written any post.
So, now I just want to share my experience when I have error once trying to connect to the CRM Online using Xrm.Tooling.Connector

Here is there error:

"Unable to Login to Dynamics CRMOrganizationWebProxyClient is nullOrganizationWebProxyClient is nullOrganizationServiceProxy is nullOrganizationServiceProxy is null"

Here is my connection string:
image

It does seem okay since I am following the example given by SDK:
image

But I receive that error as it makes me cannot connect to the CRM.

Then, how to solve it?

It is easy, just fix the URL and ensure that’s you have correct Username, password and also AuthType parameter

So, the mistake here is just the URL, change this to your unique organization, not the friendly/display name
image

*I know it can be misleading because the example is using the display name as same as you use to type your URL when you are trying to access through your browser.

*Change to:
image

To find the Unique name, please to the Customizations –> Developer Resource and find the unique name of your organization
image

Hope this helps!
Thank you

Tuesday, 6 September 2016

Utilize Custom Action to Help Filtering The Lookup View in CRM Form

Overview

Sometimes in our project, we have requirement to filter lookup based on some conditions and it can be achieved using addCustomView or addCustomFilter function.

And sometimes it is just not too easy to do it in Javascript or the complex fetch xml, so in my blog I just want to share another method to get the filtered result same as you wanted, that is using Javascript + Custom Action!

Detail

Following my previous post: http://missdynamicscrm.blogspot.sg/2014/08/crm-2013-using-addcustomfilter-to-get-filtered-lookup-field-based-on-linked-entity.html

So, considering you have this filter:
image

To get the result as per expected, you can use Custom Action.

Steps:

1. You need to create a custom action that give you output, either STRING or ENTITYCOLLECTION

2. Inside the custom action code, if you want to return string, you can use comma delimited concept, or using | as delimiter, or you can just return the Final XML Filter already.

If you use EntityCollection, you might need to parse it again.

3. Then create a javascript that can call the Custom Action, you can use this method for easy way:
http://www.magnetismsolutions.com/blog/paulnieuwelaar/2015/08/12/Call-Action-in-CRM-2015-Easily-from-JavaScript-Library

4. Then you get the result as parameter, you can just set it to the filter = “the Result” (if you use Final XML Filter as the Output) or you parse the GUID if you use the comma or | delimited concept, or if you use EntityCollection then you need to parse it back.

5. See the result

Basically, you just need to get this result:

image

Either you just easily using String as output or other method it is up to u.

But the point here is we can use Custom Action for solving complex filtering and remember that we can use impersonation also to get the data you want if it is related to the other entities as well, imagine if we also need to have multiple entities involved then it might be easier if we use Custom Action as we just replace the DLL if there is any other changes using Plugin Registration Tool.

Hope this helps!

Thanks,
Aileen

Modify the Delete (Dustbin icon) Button in the CRM Subgrid

Overview

Sometimes we need to modify the Delete button in the CRM Subgrid, example:

1. For preventing users to perform the delete button (but you dont want to just disable it)

2. Call another function or call custom function that needs client site programming (We can do plugin onDelete or onAssociate, but in case you want to show it in the client site)

3. To do impersonation

The Code

function modifyRibbon() {
    modifySubgridDeleteButtonEventHandler("subgrid_name_in_the_form", deleteSubgridRecord, true);
    discountStructureControl();
}

function deleteSubgridRecord() {
    alert("test");
}

function modifySubgridDeleteButtonEventHandler(subgridName, functionToCall, passGridControl) {
    try {
        //to store the original function ones
        var originalFunctionDeleteRecordSubgrid = Mscrm.GridCommandActions.deleteRecords;
        debugger;
        //add new standard subgrid
        Mscrm.GridCommandActions.deleteRecords = function (selectedControl, selectedControlSelectedItemReferences, selectedEntityTypeCode) {
            //if (typeof (gridControl.get_id).toString().toLowerCase() == "undefined") {} //no need since I replaced by the previous line
            if (selectedControl.get_id() != subgridName) {
                originalFunctionDeleteRecordSubgrid(selectedControl, selectedControlSelectedItemReferences, selectedEntityTypeCode);
            }
            else {
                if (passGridControl) {
                    functionToCall(selectedControl);
                }
                else {
                    functionToCall();
                }
            }
        }
    }
    catch (e) {

    }
}

Result

*After clicking the ‘Delete’ button

image

Note: This method is overwriting the CRM functions and it works for CRM 2013, for CRM 2015/2016, this function [Mscrm.GridCommandActions.deleteRecords] might have been changed, so need to find out the current function name based on your CRM Version. And again, it means it is unsupported Smile

Thanks!

Wednesday, 17 August 2016

Insert Label After the Field in CRM Form using Javascript

Hi all,
Long time I did not blog any post due to workload.
And this is my first post in this month (I know it is end of the month already)
This post basically a quick one because I have the requirement.

So, the users just want to have guidance when they entering inputs in the system.

Which we can have these solutions:

1. Tooltip (using CRM Field description)

See my post here:
http://missdynamicscrm.blogspot.sg/2014/05/crm-20112013-power-of-description.html

2. Using HTML Web Resource

This is a supported way and very useful as well. But it will make the form slower because will load the web resource and how many web resource you should create and insert. Well, you can create 1 common .html then pass the label text as the parameter

3. Using other way

So, unfortunately if those 2 solutions still not the best choice, we could go to another way using the help of CSS and Javascript.

*This is unsupported way…

And here is the Code

The Code


function insertLabelToField(fieldname, text, objSpan) {
    var elemDiv = document.getElementById(fieldname + "_c");
    //var tbl = document.createElement('table');     //elemDiv.parentNode.insertBefore(tbl, elemDiv.nextSibling);
    //var tr = tbl.insertRow();     //var td1 = tr.insertCell();     //td1.appendChild(elemDiv);     var td1 = elemDiv;     //td1.style.borderRight = "2px solid #c1c7c4";     td1.style.paddingBottom = "5.5px";
    var spanPref = null;
    if (!objSpan) {         spanPref = document.createElement('span');                 //you can change the color condition here         if (attr(fieldname).getRequiredLevel() == "required") {             spanPref.style.color = '#e31a1a';         }         else {             spanPref.style.color = '#4b4c54';         }         spanPref.style.fontSize = '10.51px';         spanPref.style.fontStyle = 'italic';     }     else {         spanPref = objSpan;     }     spanPref.id = 'spanPref_' + fieldname;         td1.appendChild(spanPref);     document.getElementById('spanPref_' + fieldname).innerText = text; }

How to Call

 
insertLabelToField(“fieldname”, "(Please describe me)");


And here is the Result

image

Hope this helps.

Thanks

Wednesday, 10 August 2016

Modify Subgrid Ribbon Behaviour Using Form Script

Introduction

A Quick post, just want to post how to Modify Subgrid button behaviour to always “Create New child record”, instead of “Add Existing record”.

This will use the similar method like described in the previous post before, but it does not call the custom funtion, it just will “redirect” the function to your “Create new record”.

Note: This is an unsupported way, for the supported way you can do two things:

1. Make the parent lookup field name to ‘Required’
2. Modify the Ribbon of the subgrid and Hide the ‘Add Existing’ button
*For your reference – > Nice post by Gareth: https://garethtuckercrm.com/2013/11/19/fixing-the-sub-grid-user-experience-in-crm-2013/

But, those will apply to the subgrid regardless the Condition, probably for the second method, you could apply some Enable/Display Rule on the subgrid ribbon.

But, if you want to do it only for specific entity and based on Parent Form condition (can be based on parent fields or even other entity values), then there is another way to do this that I will put the code in this post.

The Code

Ok, so back to the code.

Here is the code:
//function to insist create new record form instead of Add Existing
function openNewRecordFormFromSubgridButton(subgridName, passGridControl) {
    debugger;
    try {
        //to store the original function ones
        var originalFunctionAddNewStandard = Mscrm.GridRibbonActions.addNewFromSubGridStandard;
        var originalFunctionAddExistingStandard = Mscrm.GridRibbonActions.addExistingFromSubGridStandard;
        var originalFunctionAssociated = Mscrm.GridRibbonActions.addExistingFromSubGridAssociated;

        var primaryControl = document.getElementById('crmForm');
        var parentEntityId = Xrm.Page.data.entity.getId();
        var parentEntityTypeCode = Xrm.Page.data.entity.getEntityName();

        //add existing standard subgrid
        Mscrm.GridRibbonActions.addExistingFromSubGridStandard = function (gridTypeCode, gridControl) {
            if (gridControl.get_id() != subgridName) {
                originalFunctionAddExistingStandard(gridTypeCode, gridControl);
            }
            else {
                var primaryControl = document.getElementById('crmForm');
                originalFunctionAddNewStandard(gridTypeCode, parentEntityTypeCode, parentEntityId, null, gridControl);
            }
        }
  
        //and even possible for the N:N (but this is a rare scenario)
        //add associate subgrid (N:N)
        Mscrm.GridRibbonActions.addExistingFromSubGridAssociated = function (gridTypeCode, gridControl) {
            if (gridControl.get_id() != subgridName) {
                originalFunctionAssociated(gridTypeCode, gridControl);
            }
            else {
                var primaryControl = document.getElementById('crmForm');
                originalFunctionAddNewStandard(gridTypeCode, parentEntityTypeCode, parentEntityId, null, gridControl);
            }
        }
    }
    catch (e) {

    }
}

How to call:

openNewRecordFormFromSubgridButton("mysubgrid_name", true);

Result

*Previous
image
As we can see it opens lookup to look to the Existing record, it is 1:N, the record is almost possible already linked to another record, so it will make the users confused when they open this lookup.
*After
image

*And I never set any Required field to the parent lookup value, because this field is NOT always mandatory field, so it is conditional only.

Note: Use this method if you want to control the subgrid plus button based on some conditions and using the Form on Load script (easier), and it only works for the subgrid inside the form that load the function, other subgrid from another parent entity that does not have this function will not be affected, that is the advantage of using this method, to only affect subgrid of the child based on some parent entities and the function will be placed in the Parent Entity Form OnLoad and this is unsupported way.

“This is for dynamically control the subgrid behaviour through parent form onload functions based on some conditions logic, especially for 1:N relationship that usually already linked to another parent record, so that it is supposed to insist to open new Form, instead of asking the user to choose another existing record.

Hope this helps!

Thanks