Friday, October 24, 2014

OnChange part 3: Where is the clearOnChange method?

The Microsoft Dynamics CRM SDK comes with lots of functionality to affect how CRM behaves on the client side.
In a couple of articles I will discuss the opportunities ventilate my frustration over run-time event handling manipulation.

My first article in this series covered problems when trying to remove design-time defined onChange events in run-time using removeOnChange.

The second one covered problems with context awareness after manipulating event handlers using addOnChange.

To sum up the difficulties described in the two previous articles, it would be very useful to be able to say

Ok, I cannot remove the design-time event handlers, and there are some issues with manually added event handlers. So please, remove everything to give me a clean slate!

But there is no method to clear an attribute from all current event handlers.

To be able to remove an event handler, you must know its exact syntax. And you just can't remove event handlers that were introduced design-time.

It seems that introducing addOnChange and removeOnChange had a good intention and was a nice try, but they definitely didn't go all the way.

Wednesday, October 22, 2014

OnChange part 2: addOnChange with context awareness

The Microsoft Dynamics CRM SDK comes with lots of functionality to affect how CRM behaves on the client side.
In a couple of articles I will discuss the opportunities ventilate my frustration over run-time event handling manipulation.

My first article in this series covered problems when trying to remove design-time defined onChange events in run-time.

This article will cover some issues with "context awareness" that you may encounter when using addOnChange to alter the events firing from changes in the form.

A javascript web resource for a form typically has some event handlers and some business logic methods, all contained in a javascript "namespace" according to recommendations in the SDK, see section Namespaced library names.

It may look something like this:

Cinteros.JR.account = {

    // ---- Event handlers ---- //

    formLoad: function () {
        var attribute = Xrm.Page.getAttribute("numberofemployees");
        attribute.removeOnChange(Cinteros.JR.account.numberofemployees_onChange);
        attribute.addOnChange(Cinteros.JR.account.numberofemployees_onChange_with_vat);
    },

    numberofemployees_onChange: function () {
        var avgSalary = Xrm.Page.getAttribute("jr_avgsalary").getValue();
        var empCount = Xrm.Page.getAttribute("numberofemployees").getValue();
        var salaryCost = this.multiply(avgSalary, empCount);
        Xrm.Page.getAttribute("jr_salarycost").setValue(salaryCost);
    },

    numberofemployees_onChange_with_vat: function () {
        var avgSalary = Xrm.Page.getAttribute("jr_avgsalary").getValue();
        var empCount = Xrm.Page.getAttribute("numberofemployees").getValue();
        var vat = Xrm.Page.getAttribute("jr_vat_level").getValue();
        var salaryCost = this.multiply(avgSalary, empCount);
        var netsalaryCost = salaryCost - this.multiply(salaryCost, vat);
        Xrm.Page.getAttribute("jr_salarycost").setValue(netsalaryCost);
    },

    // ---- Business logic methods ---- //

    multiply: function (a, b) {
        return a * b;
    }
}

Notice how the internal method multiply is called by using syntax

  this.multiply(a, b);
This indicates that it is a method in the same (current) "namespace". This works fine and as expected when the event handler (numberofemployees_onChange in this case) has been added in the form customizations.

But when the event handler is added using attibute.addOnChange, it is not the call to the method that is passed to the function, but rather the "contents" of it. This in turn does not have a clue about my namespace, when executed.

Monday, October 20, 2014

OnChange part 1: Remove design-time event handlers

The Microsoft Dynamics CRM SDK comes with lots of functionality to affect how CRM behaves on the client side.
In a couple of articles I will discuss the opportunities ventilate my frustration over run-time event handling manipulation.

Events reacting to changes in fields can be defined design-time by making customizations to forms, and run-time by adding onChange event handlers by calling attribute.addOnChange(eventHandler).
To change the behavior run-time, there is also a method to remove designated event handlers by calling attribute.removeOnChange(eventHandler).
Read more about this in the SDK.

It is however not possible to remove event handlers that were added design-time.

The definition of methods addOnChange and removeOnChange are quite straight forward. You pass a function pointer to the method you want to add or remove. Much like you do when you define event handlers design-time.

account.name.onchange

In a scenario where a field is designed to have a specific event handler and you want to remove it to be replaced by another one, you would think that you call removeOnChange with the method name as entered in the customizations.

Sample form library:

Cinteros.JR.account = {
    formLoad: function () {
        var nameAttribute = Xrm.Page.getAttribute("name");
        nameAttribute.removeOnChange(Cinteros.JR.account.name_onChange);
        nameAttribute.addOnChange(Cinteros.JR.account.name_onChange_special);
    },

    name_onChange: function () {
        // Do standard things with name attribute
        Xrm.Utility.alertDialog("Normal function"); 
    },

    name_onChange_special: function () {
        // Do special things with name attribute
        Xrm.Utility.alertDialog("Special function"); 
    }
}

I discovered that the call to removeOnChange had no effect in this scenario. But the addOnChange added the new method as event handler. So I started digging using the F12 debugger in my browser. What does the function really do? And why does it fail silently?

Thursday, February 13, 2014

FetchXML count="-1" now returns records again

Last September I highlighted a change in the FetchXML interpretation, where using syntax like…

<fetch count="-1" mapping="logical" version="1.0">
  <entity name="account">
    <attribute name="name" />
    <attribute name="address1_city" />
  </entity>
</fetch>

…would not return any records. You had to use a count of “0” instead.

Now, when running CRM 2013, a count of “-1” returns records again :)

Perhaps someone in the product team happened to read my post and thought they should be nice to me.

That was kind.

Thursday, January 16, 2014

CRM 2011/2013 Reset Sitemap problem

As you might have seen from previous posts on my blog, I am a big fan of the XrmToolBox by Tanguy, especially the Sitemap editor is excellent in its simplicity and capabilities.

image
However, I recently ran into a problem after using the function:
Reset CRM 2013 SiteMap to default.

 

Scenario

  • New installation of CRM2013 organization.
  • Import managed Solution A, with some entities then added to sitemap.
  • Add some custom entities in unmanaged Solution B.
  • Work with sitemap for Solution B entities, either directly in the solution xml or by using XrmToolBox.
  • I’m not pleased with my manual sitemap changes, so I use the XrmToolBox function to reset the sitemap to default.
  • Now the entities from Solution A are of course not in the sitemap.
  • Re-import Solution A to get its entities back into the sitemap.
  • Solution A entities are still not showing anywhere.
  • Export Solution B unmanaged to investigate the current sitemap.
  • No traces at all of Solution A entities in sitemap.
  • Export Solution B as managed to investigate diff in sitemap.
  • Sitemap elements from Solution A appear with solutionaction="Removed".

 

Conclusion

After removing the Solution A sitemap elements, which is the result of the reset action, the system “remembers” that I do not want to see them, even after new import of the managed solution.

 

Solution

The only way I have found to solve this is to manually edit the sitemap and reintroduce the sitemap elements from Solution A into the system. After that, the Solution A entities appear as expected. Managed export of Solution B now shows nothing at all, which is correct. I can then get back to adding my own new entities.

 

Additional Problem

The solution above is possible if I have access to an unmanaged version of Solution A, but if this is something from a third party it might not be that easy to generate corresponding sitemap xml from the managed solution file.