Re-usability of Web Resources by referencing the Execution context

What’s my problem statement?

I want to create a resusable web resource that I can use to validate and format the phone numbers for accuracy on any entity that contains a phone number field.

My options

  1. To create a web resource that references each phone number field on each entity that includes a phone number i.e. Contact, Account, lead  and call this web resource on the onchange event of each field.
  2. Create one web resource and pass in the execution context, call the web resource on the on change event for each phone number field on my entities

So with option one I could improve the code by using a function and calling the function based on the field that has changed passing in the phone number and validating it, but I have to create multiple web resources for each entity and thus maintain the same code in multiple places.

With option two, on the other hand my code is in one place and is ressuable. So how do I do option two?

The Solution – using the execution context

  1. The first step is to create a web resource with the code to validate the phone number but referring to the context of the execution to pass in the variable to be used to validate the number. To do this we add the parameter context to the function i.e.  function <<Insertfunctionname>>(context). We can then reference this context as follows var oField = context.getEventSource().getValue();
  2. We now need to write our simple phone number validation and format script as below.Phone Number Format Code
  3. Save and Publish the web resource.
  4. Open the first form to add the phone number validation and format script.
  5. Click on the Form Properties and add the new web resource as a new library
  6. Select the field to add the control to using the drop down and the event will default to On Change.
  7. Click on Add and select the new library and enter the function name of the script in my case “validatephonenumber”.
  8. Critical to the process is to select the Enabled check box and the “Pass execution context as first parameter” validatephonenumber2
  9. Click ok and save and publish
  10. Repeat for each phone field on each entity
  11. Now when you open the entity and update the phone number the script is run and the number is validated, without hardcoding any field value.

End Result

You can now use this same concept to script other resusable functions using the context of the call, great for any on change common validation of formatting function.

I hope this helps to simplify your development and time to deliver critical common functions.

Microsoft Dynamics CRM 2011 “Polaris” release and its potential impact on current deployments

As part of its continual evolution of Microsoft Dynamics CRM, Microsoft will soon release its December 2012 Service Update, codenamed Polaris. (Following the Polaris release, there will be three more star or star constellation themed releases: Orion, Leo and Vega.)

The Polaris release contains a range of new capabilities, including new sales and customer service user interface options, cross browser support, new integration points for Yammer, Skype, and Bing Maps, Microsoft Office 2013 compatibility, and a bulk data API. More information on this release, including an official Release Preview Guide from Microsoft, can be found on the Microsoft CRM site http://crm.dynamics.com/en-us/polaris.

This release will be rolled out from mid/end December and through January, and while most of the changes in this Service Update will be for customers using Microsoft Dynamics CRM 2011 Online, those using the on-premise release will also be able to take advantage of cross-browser support. What does this mean? To quote from the documentation: “Microsoft is expanding the range of browsers supported to include versions of Mozilla Firefox and Google Chrome on Windows PCs. Firefox and Apple Safari will be supported on Macintosh desktop computers. There will also be Safari support on Apple iPad tablets for sales users. This sales experience on iPad adds flexibility for the mobile salesperson.”

This potentially has an impact on any current deployments of Dynamics CRM 2011 that contain any JavaScript or HTML programming (for example, any. web resources that have been created to hide/show fields etc.). Organisations that are potentially impacted by this update need to work with their service providers or themselves to ensure that any JavaScript that has been deployed will comply with the cross-browser update.

The process to review the code is as follows and the time it will take will depend obviously on the complexity and functionality of the JavaScript that has been deployed:

1. Download and install the ‘Microsoft Dynamics CRM 2011 Custom Code Validation Tool’ solution from Microsoft at http://www.microsoft.com/en-us/download/details.aspx?id=30151 . This tool is free to download.
2. Import your CRM solution into the your UAT/DEV environment.
3. The solution will run and provide a colour-coded review of the code in the solution, identifying code items that will fail and might fail following the release of the December 2012 update.
4. For any areas where the code may break, a developer will be required to update the code and fix the issue; this may be as a result of an upgrade where the JavaScript has not been fully converted (using old V4 supported code) or where there are specific commands that only Internet Explorer can interpret.
5. Once the changes have been applied, the updated solution needs to be tested and rolled out.

As a guide, we would expect for most customers this process will take from 4-8 hours to complete; for larger, more complex implementations this process may take longer.

The following blog post by Microsoft details this process in far more detail: http://community.dynamics.com/product/crm/crmtechnical/b/crmteamblog/archive/2012/06/21/microsoft-dynamics-crm-2011-custom-code-validation-tool-released.aspx . If you would like to know more, please don’t hesitate to contact us at Intergen (http://intergen.co.nz/Contact-Us/enquiry-form ).

How to find out which action raised the OnSave event in a Form using event>mode

Recently, I was asked by a customer if it was possible to execute some javascript when an Opportunity is marked as won. As you all know, the value of statecode is in fact on a separate dialog box and technically, there is no way to capture the event. However, this is another way around it, and that is the use the event.Mode value to determine which action raised the OnSave event in the first place.

Here is the list of events:

  • None : 0
  • Save : 1
  • SaveAndClose : 2
  • Delete : 3
  • Load : 4
  • Deactivate : 5
  • Reactivate : 6
  • Email Send : 7
  • Email Reply : 8
  • Email Forward : 9
  • Kb Submit : 10
  • Kb Reject : 11
  • Kb Publish : 12
  • Kb UnPublish : 13
  • Kb Rate : 14
  • Lead Unqualify : 15
  • Lead Qualify : 16
  • Quote Accept : 17
  • Quote CreateOrder : 18
  • Order ProcessOrder : 19
  • Opportunity AddRelatedOrder : 21
  • Opportunity AddRelatedQuote : 22
  • Opportunity AddRelatedInvoice : 23
  • Quote CreateRevision : 24
  • Quote CloseQuote : 25
  • Order CancelOrder : 26
  • Invoice Close : 27
  • Quote GetProducts : 28
  • Quote Activate : 29
  • Email ReplyAll : 30
  • Contract Hold : 31
  • Contract ReleaseHold : 32
  • Contract Cancel : 33
  • Contract Renew : 34
  • Product ConvertToKit : 35
  • Product ConvertFromKit : 36
  • ContractDetail Cancel : 37
  • Contract Invoice : 38
  • Contract Clone : 39
  • Incident Cancel : 40
  • Email Assign : 41
  • Change SalesStage : 42
  • SalesOrder GetProducts : 43
  • InvoiceGetProducts : 44
  • TemplateMakeOrgAvailable : 45
  • TemplateMakeOrgUnavailable : 46
  • Assign : 47
  • IncidentAssignToUser : 49
  • OrderLock : 50
  • OrderUnlock : 51
  • InvoiceLock : 52
  • InvoiceUnlock : 53
  • ConvertResponse : 54
  • ReportMakeOrgAvailable : 60
  • ReportMakeOrgUnavailable : 61
  • WorkflowAddCheckStep : 62
  • WorkflowUpdateCondition : 63
  • WorkflowCreateAction : 64
  • SendInvite : 65
  • WorkflowAddElseIfStep : 66
  • WorkflowAddElseStep : 67
  • WorkflowDeleteStep : 68

Example Usage :

if(event.Mode == 5) //deactivation

{

// Do some custom logic here

}

 

If you dont know which action triggered the event, you can use the following line in the onSave event of the form to find out :

alert(event.Mode);

Changing the default lookup type of a regarding field

When opening a lookup that can select from multiple entity types, you may want to use a different default entity in the lookup dialog. The following script changes the default entity of the regardingobjectid field in an activity to contacts:

 

if (crmForm.all.regardingobjectid != null) {
    crmForm.all.regardingobjectid.setAttribute("defaulttype", "2");
}

 

The 2 refers to contact, just change to reflect the object you wish to set as the default.

Retrieving values from lookup entity relationships without using webservices

Note the values that you want to pull through need to be on the lookup view of that entity. Item in bold is the key part.

//Defines the lookup entity to retrieve values from

var lookup = crmForm.all.<<LookupField>>;

if(lookup .DataValue != null)

{

//Using key values to retrieve the value of the item from the lookup entity. Items[0] refers to the selected instance of the entity of the form.

 var lookupfieldvalue =  lookup.items[0].keyValues.<<field_on_lookup_view>>.value;

}

Google Maps integration

Place the code in the on load event, change the address fields to your applicable fields, populate the country field if not defaulted with teh right country and then update the iframe source details. You make want to add a checkbox on the map tab to control when the below code is applied to the iframe as you do not want the map loading everytime you open up your record (slows down the loading of the record). Happy Mapping!!

var CRM_FORM_TYPE_CREATE = 1;

var CRM_FORM_TYPE_UPDATE = 2;

var LiveSearchURL = "";

 if(IsOnline())

{

                switch (crmForm.FormType)

                {

                                case CRM_FORM_TYPE_CREATE:

                                                // Point to the Microsoft Live Search home page when creating an account

                                                LiveSearchURL = "http://maps.google.com&quot;;  

                                                break;

                                 case CRM_FORM_TYPE_UPDATE:

                                               // Use Live search with this account’s name

                                                LiveSearchURL = http://maps.google.com/maps?q=;

                                                // Encode the account name and add it to the search string

                                                                LiveSearchURL += crmForm.all.address2_line1.DataValue;

                                                LiveSearchURL += " ";

                                                                LiveSearchURL += crmForm.all.address2_line2.DataValue;

                                                                LiveSearchURL += " ";

                                                                LiveSearchURL += crmForm.all.address2_city.DataValue;

                                                                LiveSearchURL += " ";

                                                                LiveSearchURL += crmForm.all.address2_country.DataValue;

                                                break;

                }

}

 

// Set the IFRAME’s URL

crmForm.all.IFRAME_MAP.src = LiveSearchURL;

Defaulting the search criteria of a lookup

Option 1 – Hard coding the search criteria with a text value
 

crmForm.all.INSERTLOOKUPFIELD.additionalparams = "search=INSERTTEXTSEARCHCRITERIA";

Option 2 – Filtering the lookup search with a value from another lookup

For example when you want to filter the primary contacts lookup on an Account with only the contacts associated to that account by default. The code is split into a function and then  the code to call the function.

Function

document.FilteredLookup = function(criteria, lookup)
    {
    if(criteria == null || lookup == null)
        {
        return;
        }
     var filterCriteria = IsNull(criteria.DataValue) ? "" : criteria.DataValue[0].name;
     lookup.additionalparams = "search=" + filterCriteria;
    }

Code to call the function 

document.FilteredLookup(crmForm.all.INSERTFIELD, crmForm.all.INSERTFIELD);