Featured image of post Xrm.Page Object Deprecation: Check your Dynamics 365 Customer Engagement JScript

Xrm.Page Object Deprecation: Check your Dynamics 365 Customer Engagement JScript

I must admit, first of all, that I missed the announcement around this at the time. However, after doing some playing around with the new Solution Checker feature within the Common Data Service, after a very informative User Group presentation from MVP extraordinaire Andrew Bibby, I was very quickly brought up to speed and thought this whole topic would be a great subject for this week’s blog post.

Involving custom code, either via a C# plug-in or a JScript form function, can throw open a whole smorgasbord of additional functionality to meet your business requirements within Dynamics 365 Customer Engagement. Although I am a huge proponent of extending the application in this manner, developers should always fully evaluate the range of out of the box features available within the application before they start resorting to code. Business Rules are a good example of a feature that may get overlooked in this regard and, with the range of options they offer, are much easier to maintain/support when compared with a custom JScript function. Custom code can also become a nightmare as part of any upgrade testing between major versions, meaning that you have to dedicate additional time for testing to ensure that nothing breaks as a consequence. Chiefly, this is because Microsoft will, from time to time, remove API features entirely or replace them with “better” routes to achieve the same end. Microsoft is typically very good at signposting when a feature is going onto the scrapheap, and you will almost always be given the period between at least two major versions of an application release to address any issues. It’s therefore crucial for developers to keep themselves abreast of any relevant release notes and take proactive steps to fix their code whenever a particular method, endpoint etc. is deprecated; and, given that I missed this one entirely, I include myself in this category as well 🙂

As part of version 9 of Dynamics 365 Customer Engagement, the primary method for accessing various properties via JScript on a form within the application - Xrm.Page - is now deprecated. Developers must now instead access all properties relating to the page by passing the executionContext object to their functions. Then, with some additional re-tinkering around, the entire range of form properties we are used to working with are fully exposed. I can imagine the Xrm.Page object is used across a whole range of different deployments today and, therefore, has the potential to cause some future anguish if not properly addressed. But how exactly do you go about addressing this and getting your code up to spec? Let’s assume we have the following JScript function for the Contact entity that was developed a few years ago using the Xrm.Page object:

function changeAddressLabels() {
    Xrm.Page.getControl("address1_composite_compositionLinkControl_address1_line1").setLabel("Address 1");
    Xrm.Page.getControl("address1_composite_compositionLinkControl_address1_line2").setLabel("Address 2");
    Xrm.Page.getControl("address1_composite_compositionLinkControl_address1_line3").setLabel("Address 3");
    Xrm.Page.getControl("address1_composite_compositionLinkControl_address1_city").setLabel("Town");
    Xrm.Page.getControl("address1_composite_compositionLinkControl_address1_stateorprovince").setLabel("County");
    Xrm.Page.getControl("address1_composite_compositionLinkControl_address1_postalcode").setLabel("Postal Code");
    Xrm.Page.getControl("address1_composite_compositionLinkControl_address1_country").setLabel("Country");
    Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_line1").setLabel("Address 1");
    Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_line2").setLabel("Address 2");
    Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_line3").setLabel("Address 3");
    Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_city").setLabel("Town");
    Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_stateorprovince").setLabel("County");
    Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_postalcode").setLabel("Postal Code");
    Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_country").setLabel("Country");
}

The function is straightforward, and long-standing readers of the blog may remember this bit of code, which modifies the display name of the composite control Address 1/Address 2 fields on the Contact to become more regionally relevant for UK users of the application. When we look at the configuration of the function in more detail within an existing Dynamics 365 Customer Engagement deployment, we observe that a) it accepts and receives no parameter values and b) is configured on the Main form for the Entity as an OnLoad function, with the following properties:

To get things updated to use the new executionContext object, we must make the following changes:

  1. Pass the executionObject as a parameter for the changeAddressLabels function.
  2. Get the formContext from the executionObject parameter and store this within a separate variable.
  3. Replace all references to the Xrm.Page object with the newly declared formContext variable.
  4. Because the script will error if the fields are not located on the form, we need to also add in some additional logic that will only attempt to rename each field if it exists on the form.
  5. Modify the above event handler on the Contact Main form to tick the Pass execution context as first parameter checkbox.

Our updated code should, therefore, resemble the following:

function changeAddressLabels(executionContext) {

	//Get formContext
	
	var formContext = executionContext.getFormContext();
	
	//Check to see if the control is on the form and, if so, rename it accordingly.
  
  if (formContext.getControl("address1_composite_compositionLinkControl_address1_line1"))
    formContext.getControl("address1_composite_compositionLinkControl_address1_line1").setLabel("Address 1");
  if (formContext.getControl("address1_composite_compositionLinkControl_address1_line2"))
    formContext.getControl("address1_composite_compositionLinkControl_address1_line2").setLabel("Address 2");
  if (formContext.getControl("address1_composite_compositionLinkControl_address1_line3"))
    formContext.getControl("address1_composite_compositionLinkControl_address1_line3").setLabel("Address 3");
  if (formContext.getControl("address1_composite_compositionLinkControl_address1_city"))
    formContext.getControl("address1_composite_compositionLinkControl_address1_city").setLabel("Town");
  if (formContext.getControl("address1_composite_compositionLinkControl_address1_stateorprovince"))
    formContext.getControl("address1_composite_compositionLinkControl_address1_stateorprovince").setLabel("County");
  if (formContext.getControl("address1_composite_compositionLinkControl_address1_postalcode"))
    formContext.getControl("address1_composite_compositionLinkControl_address1_postalcode").setLabel("Postal Code");
  if (formContext.getControl("address1_composite_compositionLinkControl_address1_country"))
    formContext.getControl("address1_composite_compositionLinkControl_address1_country").setLabel("Country");
  if (formContext.getControl("address2_composite_compositionLinkControl_address2_line1"))
    formContext.getControl("address2_composite_compositionLinkControl_address2_line1").setLabel("Address 1");
  if (formContext.getControl("address2_composite_compositionLinkControl_address2_line2"))
    formContext.getControl("address2_composite_compositionLinkControl_address2_line2").setLabel("Address 2");
  if (formContext.getControl("address2_composite_compositionLinkControl_address2_line3"))
    formContext.getControl("address2_composite_compositionLinkControl_address2_line3").setLabel("Address 3");
  if (formContext.getControl("address2_composite_compositionLinkControl_address2_city"))
    formContext.getControl("address2_composite_compositionLinkControl_address2_city").setLabel("Town");
  if (formContext.getControl("address2_composite_compositionLinkControl_address2_stateorprovince"))	
    formContext.getControl("address2_composite_compositionLinkControl_address2_stateorprovince").setLabel("County");
  if (formContext.getControl("address2_composite_compositionLinkControl_address2_postalcode"))
    formContext.getControl("address2_composite_compositionLinkControl_address2_postalcode").setLabel("Postal Code");
  if (formContext.getControl("address2_composite_compositionLinkControl_address2_country"))
    formContext.getControl("address2_composite_compositionLinkControl_address2_country").setLabel("Country");
}

And, likewise, our above Handler Properties window should look like this:

So, as we can see, the amount of effort involved is not too great and, even if you have to carry out these changes to multiple functions, I’m fairly confident that find and replace can be innovatively utilised to help you along. You can find out more about this impending change, along with some useful code examples, by reading the dedicated Microsoft Docs page on this very subject.

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy