This is an accompanying blog post to my YouTube video Dynamics 365 Customer Engagement Deep Dive: Creating a Basic Jscript Form Function, the first in a series that aims to provide tutorials on how to accomplish developer focused tasks within Dynamics 365 Customer Engagement. You can watch the video in full below:

Below you will find links to access some of the resources discussed as part of the video and to further reading topics.

PowerPoint Presentation (click here to download)

Full Code Sample

function changeAddressLabels() {

    //Get the control for the composite address field and then set the label to the correct, Anglicised form. Each line requires the current control name for 'getControl' and then the updated label name for 'setLabel'

    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");

    if (Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_line1"))
        Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_line1").setLabel("Address 1");

    if (Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_line2"))
        Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_line2").setLabel("Address 2");

    if (Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_line3"))
        Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_line3").setLabel("Address 3");

    if (Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_city"))
        Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_city").setLabel("Town");

    if (Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_stateorprovince"))
        Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_stateorprovince").setLabel("County");

    if (Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_postalcode"))
        Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_postalcode").setLabel("Postal Code");

    if (Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_country"))
        Xrm.Page.getControl("address2_composite_compositionLinkControl_address2_country").setLabel("Country");
}

Download/Resource Links

Visual Studio 2017 Community Edition

Setup a free 30 day trial of Dynamics 365 Customer Engagement

W3 Schools JavaScript Tutorials

Source Code Management Solutions

Further Reading

MSDN – Use JavaScript with Microsoft Dynamics 365

MSDN – Use the Xrm.Page. object model

MSDN – Xrm.Page.ui control object

MSDN – Overview of Web Resources

Debugging custom JavaScript code in CRM using browser developer tools (steps are for Dynamics CRM 2016, but still apply for Dynamics 365 Customer Engagement)

Have any thoughts or comments on the video? I would love to hear from you! I’m also keen to hear any ideas for future video content as well. Let me know by leaving a comment below or in the video above.

In last week’s post, we took a look at how a custom Workflow activity can be implemented within Dynamics CRM/Dynamics 365 for Customer Engagement to obtain the name of the user who triggered the workflow. It may be useful to retrieve this information for a variety of different reasons, such as debugging, logging user activity or to automate the population of key record information. I mentioned in the post the “treasure trove” of information that the IWorkflowContext interface exposes to developers. Custom Workflow activities are not unique in having execution-specific information exposable, with an equivalent interface at our disposal when working with plug-ins. No prizes for guessing its name – the IPluginExecutionContext.

When comparing both interfaces, some comfort can be found in that they share almost identical properties, thereby allowing us to replicate the functionality demonstrated in last weeks post as Post-Execution Create step for the Lead entity. The order of work for this is virtually the same:

  1. Develop a plug-in C# class file that retrieves the User ID of the account that has triggered the plugin.
  2. Add supplementary logic to the above class file to retrieve the Display Name of the User.
  3. Deploy the compiled .dll file into the application via the Plug-in Registration Tool, adding on the appropriate execution step.

The emphasis on this approach, as will be demonstrated, is much more focused towards working outside of the application; something you may not necessarily be comfortable with. Nevertheless, I hope that the remaining sections will provide enough detail to enable you to replicate within your own environment.

Developing the Class File

As before, you’ll need to have ready access to a Visual Studio C# Class file project and the Dynamics 365 SDK. You’ll also need to ensure that your project has a Reference added to the Microsoft.Xrm.Sdk.dll. Create a new Class file and copy and paste the following code into the window:

using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;

namespace D365.BlogDemoAssets.Plugins
{
    public class PostLeadCreate_GetInitiatingUserExample : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            // Obtain the execution context from the service provider.

            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

            // Obtain the organization service reference.
            IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

            // The InputParameters collection contains all the data passed in the message request.
            if (context.InputParameters.Contains("Target") &&
                context.InputParameters["Target"] is Entity)

            {
                Entity lead = (Entity)context.InputParameters["Target"];

                //Use the Context to obtain the Guid of the user who triggered the plugin - this is the only piece of information exposed.
      
                Guid user = context.InitiatingUserId;

                //Then, use GetUserDisplayCustom method to retrieve the fullname attribute value for the record.

                string displayName = GetUserDisplayName(user, service);

                //Build out the note record with the required field values: Title, Regarding and Description field

                Entity note = new Entity("annotation");
                note["subject"] = "Test Note";
                note["objectid"] = new EntityReference("lead", lead.Id);
                note["notetext"] = @"This is a test note populated with the name of the user who triggered the Post Create plugin on the Lead entity:" + Environment.NewLine + Environment.NewLine + "Executing User: " + displayName;

                //Finally, create the record using the IOrganizationService reference

                service.Create(note);
            }
        }
    }
}

Note also that you will need to rename the namespace value to match against the name of your project.

To explain, the code replicates the same functionality developed as part of the Workflow on last week’s post – namely, create a Note related to a newly created Lead record and populate it with the Display Name of the User who has triggered the plugin.

Retrieving the User’s Display Name

After copying the above code snippet into your project, you may notice a squiggly red line on the following method call:

The GetUserDisplayName is a custom method that needs to be added in manually and is the only way in which we can retrieve the Display Name of the user, which is not returned as part of the IPluginExecutionContext. We, therefore, need to query the User (systemuser) entity to return the Full Name (fullname) field, which we can then use to populate our newly create Note record. We use a custom method to return this value, which is provided below and should be placed after the last 2 curly braces after the Execute method, but before the final 2 closing braces:

private string GetUserDisplayName(Guid userID, IOrganizationService service)
    {
        Entity user = service.Retrieve("systemuser", userID, new ColumnSet("fullname"));
        return user.GetAttributeValue<string>("fullname");
    }

Deploy to the application using the Plug-in Registration Tool

The steps involved in this do not differ greatly from what was demonstrated in last week’s post, so I won’t repeat myself 🙂 The only thing you need to make sure you do after you have registered the plug-in is to configure the plug-in Step. Without this, your plug-in will not execute. Right-click your newly deployed plug-in on the main window of the Registration Tool and select Register New Step:

On the form that appears, populate the fields/values indicated below:

  • Message: Create
  • Primary Entity: Lead
  • Run in User’s Context: Calling User
  • Event Pipeline Stage of Execution: Post-Operation

The window should look similar to the below if populated correctly. If so, then you can click Register New Step to update the application:

All that remains is to perform a quick test within the application by creating a new Lead record. After saving, we can then verify that the plug-in has created the Note record as intended:

Having compared both solutions to achieve the same purpose, is there a recommended approach to take?

The examples shown in the past two blog posts indicate excellently how solutions to specific scenarios within the application can be achieved via differing ways. As clearly evidenced, one could argue that there is a code-heavy (plug-in) and a light-touch coding (custom Workflow assembly) option available, depending on how comfortable you are with working with the SDK. Plug-ins are a natural choice if you are confident working solely within Visual Studio or have a requirement to perform additional business logic as part of your requirements. This could range from complex record retrieval operations within the application or even an external integration piece involving specific and highly tailored code. The Workflow path clearly favours those of us who prefer to work within the application in a supported manner and, in this particular example, can make certain tasks easier to accomplish. As we have seen, the act of retrieving the Display Name of a user is greatly simplified when we go down the Workflow route. Custom Workflow assemblies also offer greater portability and reusability, meaning that you can tailor logic that can be applied to multiple different scenarios in the future. Code reusability is one of the key drivers in many organisations these days, and the use of custom Workflow assemblies neatly fits into this ethos.

These are perhaps a few considerations that you should make when choosing the option that fits the needs of your particular requirement, but it could be that the way you feel most comfortable with ultimately wins the day – so long as this does not compromise the organisation as a consequence, then this is an acceptable stance to take. Hopefully, this short series of posts have demonstrated the versatility of the application and the ability to approach challenges with equally acceptable pathways for resolution.

Dynamics CRM/Dynamics 365 for Customer Engagement (CRM/D365CE) is an incredibly flexible application for the most part. Regardless of how your business operates, you can generally tailor the system to suit your requirements and extend it to your heart’s content; often to the point where it is completely unrecognisable from the base application. Notwithstanding this argument, you will come across aspects of the application that are (literally) hard-coded to behave a certain way and cannot be straightforwardly overridden via the application interface. The most recognisable example of this is the Lead Qualification process. You are heavily restricted in how this piece of functionality acts by default but, thankfully, there are ways in which it can be modified if you are comfortable working with C#, JScript and Ribbon development.

Before we can start to look at options for tailoring the Lead Qualification process, it is important to understand what occurs during the default action within the application. In developer-speak, this is generally referred to as the QualifyLead message and most typically executes when you click the button below on the Lead form:

When called by default, the following occurs:

  • The Status/Status Reason of the Lead is changed to Qualified, making the record inactive and read-only.
  • A new OpportunityContact and Account record is created and populated with (some) of the details entered on the Lead record. For example, the Contact record will have a First Name/Last Name value supplied on the preceding Lead record.
  • You are automatically redirected to the newly created Opportunity record.

This is all well and good if you are able to map your existing business processes to the application, but most organisations will typically differ from the applications B2B orientated focus. For example, if you are working within a B2C business process, creating an Account record may not make sense, given that this is typically used to represent a company/organisation. Or, conversely, you may want to jump straight from a Lead to a Quote record. Both of these scenarios would require bespoke development to accommodate currently within CRM/D365CE. This can be broadly categorised into two distinct pieces of work:

  1. Modify the QualifyLead message during its execution to force the desired record creation behaviour.
  2. Implement client-side logic to ensure that the user is redirected to the appropriate record after qualification.

The remaining sections of this post will demonstrate how you can go about achieving the above requirements in two different ways.

Our first step is to “intercept” the QualifyLead message at runtime and inject our own custom business logic instead

I have seen a few ways that this can be done. One way, demonstrated here by the always helpful Jason Lattimer, involves creating a custom JScript function and a button on the form to execute your desired logic. As part of this code, you can then specify your record creation preferences. A nice and effective solution, but one in its guise above will soon obsolete as a result of the SOAP endpoint deprecation. An alternative way is to instead deploy a simplistic C# plugin class that ensures your custom logic is obeyed across the application, and not just when you are working from within the Lead form (e.g. you could have a custom application that qualifies leads using the SDK). Heres how the code would look in practice:

public void Execute(IServiceProvider serviceProvider)
    {
        //Obtain the execution context from the service provider.

        IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

        if (context.MessageName != "QualifyLead")
            return;

        //Get a reference to the Organization service.

        IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
        IOrganizationService service = factory.CreateOrganizationService(context.UserId);

        //Extract the tracing service for use in debugging sandboxed plug-ins

        ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

        tracingService.Trace("Input parameters before:");
        foreach (var item in context.InputParameters)
        {
            tracingService.Trace("{0}: {1}", item.Key, item.Value);
        }

        //Modify the below input parameters to suit your requirements.
        //In this example, only a Contact record will be created
        
        context.InputParameters["CreateContact"] = true;
        context.InputParameters["CreateAccount"] = false;
        context.InputParameters["CreateOpportunity"] = false;

        tracingService.Trace("Input parameters after:");
        foreach (var item in context.InputParameters)
        {
            tracingService.Trace("{0}: {1}", item.Key, item.Value);
        }
    }

To work correctly, you will need to ensure this is deployed out on the Pre-Operation stage, as by the time the message reaches the Post-Operation stage, you will be too late to modify the QualifyLead message.

The next challenge is to handle the redirect to your record of choice after Lead qualification

Jason’s code above handles this effectively, with a redirect after the QualifyLead request has completed successfully to the newly created Account (which can be tweaked to redirect to the Contact instead). The downside of the plugin approach is that this functionality is not supported. So, if you choose to disable the creation of an Opportunity record and then press the Qualify Lead button…nothing will happen. The record will qualify successfully (which you can confirm by refreshing the form) but you will then have to manually navigate to the record(s) that have been created.

The only way around this with the plugin approach is to look at implementing a similar solution to the above – a Web API request to retrieve your newly created Contact/Account record and then perform the necessary redirect to your chosen entity form:

function redirectOnQualify() {

    setTimeout(function(){
        
        var leadID = Xrm.Page.data.entity.getId();

        leadID = leadID.replace("{", "");
        leadID = leadID.replace("}", "");

        var req = new XMLHttpRequest();
        req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.0/leads(" + leadID + ")?$select=_parentaccountid_value,_parentcontactid_value", true);
        req.setRequestHeader("OData-MaxVersion", "4.0");
        req.setRequestHeader("OData-Version", "4.0");
        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        req.setRequestHeader("Prefer", "odata.include-annotations=\"OData.Community.Display.V1.FormattedValue\"");
        req.onreadystatechange = function () {
            if (this.readyState === 4) {
                req.onreadystatechange = null;
                if (this.status === 200) {
                    var result = JSON.parse(this.response);
                    
                    //Uncomment based on which record you which to redirect to.
                    //Currently, this will redirect to the newly created Account record
                    var accountID = result["_parentaccountid_value"];
                    Xrm.Utility.openEntityForm('account', accountID);

                    //var contactID = result["_parentcontactid_value"];
                    //Xrm.Utility.openEntityForm('contact', contactID);

                }
                else {
                    alert(this.statusText);
                }
            }
        };
        req.send();
        
    }, 6000);     
}

The code is set to execute the Web API call 6 seconds after the function triggers. This is to ensure adequate time for the QualifyLead request to finish and make the fields we need available for accessing.

To deploy out, we use the eternally useful Ribbon Workbench to access the existing Qualify Lead button and add on a custom command that will fire alongside the default one:

As this post has hopefully demonstrated, overcoming challenges within CRM/D365CE can often result in different – but no less preferred – approaches to achieve your desired outcome. Let me know in the comments below if you have found any other ways of modifying the default Lead Qualification process within the application.

A colleague recently asked me this question, and I’ll admit that it took me a few minutes to think about the answer. Learning how to write code that extends functionality within or outside of CRM is not something that you can just pick up from scratch. You usually need to have good experience with coding first, before you can safely venture into writing your first plugin or form level JScript function. Fundamental, and arguably, crucial knowledge of the CRM platform is essential too, as this ensures that you don’t put forward solutions that the application can handle natively. In this week’s blog post, I will first clarify what CRM Development actually means, before outlining  my “top tips” on how you can develop your skills to become a superstar CRM Developer.

So what is CRM Development, and is it the same as CRM Customisation?

It’s important that we first clarify what the difference is between these two types of activities, as although there is some cross-over, often they are split out into two distinct roles – a CRM Customiser and CRM Developer. Someone who occupies the first of these roles frequently spends the majority of their time working with CRM Solutions and the Customizations area of CRM. Customisers will commonly be involved in the creation of new entities, fields, system views, processes, business rule & workflows, to name a few. As a consequence, they will more often than not have a great deal knowledge of what the platform is capable of and are generally in the best position to offer support and mentoring to colleagues who are struggling with something in CRM (for example, how to create a personal view).

In comparison, a CRM Developer may spend very little time working with solutions and customisations; although they will be expected to have a general awareness of what the platform is capable of doing,  they will mostly only ever be concerned with modifying plug-ins, plug-in steps and web resources from within solutions. CRM Development instead encompasses a broad canvas of work, all of which is geared towards extending the native functionality of the application. An example list may include:

  • Writing form level JScript, for scenarios where a Business Rule can’t achieve the desired results (we’ve already learned the importance of considering Business Rules as a first step option in these scenarios)
  • Developing custom plug-ins in C#/VB.NET to execute at specific trigger points within the underlying database transaction e.g. after a Contact record has been updated.
  • Building custom workflow assemblies in C#/VB.NET to further enhance the options available as part of a workflow or dialog.
  • Setting up custom Web Resources in HTML/Silverlight, that can be embedded within CRM forms or dashboards.

A good way of remembering the difference is to remember that CRM Customisation can all be done from within the application itself, whereas CRM Development involves work created outside the application to achieve specific business requirements.

Now that we’ve got that out of the way, here’s my top 5 list on how you can learn CRM Development:

Learn C# First

As well as providing you with everything you would ever need from a plug-in/custom workflow development perspective, having a good grasp of C# can make learning JScript a lot more easier. Both languages have a lot of similarity, with some important differences that require noting. First, JScript is largely indifferent when it comes to working with data types, whereas C# is very fussy when it comes to declaring and casting your data types correctly. Secondly, whereas C# development work can be assisted via the use of early-bound class files, JScript can be annoyingly unsympathetic when you write code, with errors only cropping up when you attempt to run your code. Putting aside these differences though, being able to say that you have a good grasp of C# on your C.V. can assist greatly when seeking out roles involving CRM, particularly given such roles will be looking for experience of integrating CRM with third party applications; C# is your Swiss army knife in these situations.

The SDK is your treasure trove.

There are countless number of code examples & snippets enclosed within the SDK, which include all of the languages that you would use to extend CRM – JScript, C# and even VB.NET! These are typically in a state where you can easily deploy them to a test CRM environment, execute them and then playback within Visual Studio via the Plugin Profiler, so you can understand what they are doing.  The enclosed help file (which is replicated fully on the MSDN website) is also really detailed in explaining what you can do when developing for CRM. You can download the latest version of the SDK (updated recently for the 2016 Spring Wave) here.

Get an MSDN Subscription

I have extolled the virtues of what an MSDN subscription can provide to Microsoft professionals previously, so I won’t cover old ground. What I will highlight from this is that the Imagine Academy, included as part of a subscription, contains nearly all of the courses found on the Dynamics Learning Portal (available to CRM partners as a learning resource “hub” for all Dynamics products). It also gives you access to a number of important, developer-focused resources that you add to your arsenal and use to further enhance your knowledge of C#, JScript etc. If you’re fortunate enough to have enough money to obtain an Enterprise MSDN Subscription, or your employer has a few spare licenses, then you will be able to get your hands on a coveted CRM On-Premise license key as well. Working with the application in whatever capacity you can is the best and surest way to learn, as opposed to simply watching videos and reading online articles.

Pass those Exams

There are a wide plethora of different CRM exams available to take currently, and it can be quite confusing deciding which ones will benefit you best on your road to become a CRM Developer. I would suggest that the best exams to target a passing mark on would be the following:

The question you may be asking though is “How important are exams, compared with actual work experience?”. I have heard many debates surrounding the importance of certification, on both sides of the argument; one criticism is that they are generally not a good way equipping candidates with the practical, real-life knowledge and experience that ultimately must come to the fore when working with CRM on a day-to-day basis. Another argument against them is that they can sometimes draw you towards focusing on features of a particular application that is either not very good or is done much better by an alternative product. Notwithstanding this, I think exams hold an important place in demonstrating to colleagues and potential recruiters just how serious you are about your career and in ensuring that you keep yourself up-to-date with the appropriate technology – in these modern times, staying off the ball for as little as a month can put you behind! Going back to the original purpose of this post, the curriculum on both of these exams will leave you in a position where you have achieved a good balance of knowledge: both of what CRM, as a platform, is capable of out of the box, and what you can do to develop further solutions for the application.

And finally, believe in yourself

This last tip may sound a little bit clichéd, but achieving your desire to become good at CRM Development is something that only you have control over. The journey may be hard, and you will often fail more than you succeed at first; but if you keep working at it, never give up and, most importantly, trust in yourself and your abilities, then you will succeed in increasing your knowledge and expertise in CRM.

I was having a chat with a colleague recently about the new Interactive Service Hub (ISH) in CRM, in particular the new entity forms that are used as part of this. One of the questions that came up was “From a form scripting point of view, do ISH forms let you utilise all of the same references, properties and methods available as part of a Main form?”. As is generally the case in these situations, we can turn to our good friends TechNet and MSDN for answers. Specifically, we are able to find out the following on MSDN:

All the form scripting events and methods supported by the CRM mobile clients (phone and tablet) are supported in the interactive service hub.

If your organisation is fortunate enough to be using CRM 2016 Update 1 or CRM 2016 Service Pack 1, then you can also utilise the following methods/events as well:

Source: https://msdn.microsoft.com/en-us/library/mt671135.aspx#Anchor_1

So what does this mean in practical terms and how should this factor into your decision to utilise Interactive Forms over standard CRM forms? Here are a few things to consider, as well as my own thoughts on the best way to proceed:

If you are on CRM 2016, then get yourself Update 1/Service Pack 1 ASAP

There are a number of important new methods that can be used for interactive forms as part of this update. For example, you get much better options when it comes to working with IFRAME controls, interacting with the currently loaded record you are working with (via getID), loading a new record form (via openEntityForm or openQuickCreate) and setting focus to a particular field on a form (via setFocus). This goes above and beyond what is currently supported via the CRM tablet apps, and it is good to see that this CRM update has added these in. Having access to these methods may help to decide whether you can safely migrate or start using ISH forms within your organisation. And, as we have seen previously, the update process to SP1 for CRM 2016 is relatively straightforward, so why wouldn’t you look at upgrading?

Be sure you familiarise yourself with Interactive Form debugging

Anyone who works with CRM form scripting will be familiar with the trials and tribulations of browser debugging your scripts via Developer Tools on your browser of choice: open up your script library, set your breakpoints and then perform the actions needed to trigger your script. Try this with the new Interactive Forms, and you will notice that your custom library is not loaded onto the form. What the fudge?!?

Before panicking too much, the good news is that scripts can still be debugged, but you just have to go down a slightly different route. The CRM Team have written an excellent blog post that covers not just debugging for interactive forms, but for all forms as well. The first two options suggested seem to be the most straight-forward way of debugging interactive forms, but you can’t help but laugh at the fact that one of the suggested options is to use functionality within Google Chrome! 🙂 Joking aside, using Dynamic JScript in the manner outlined looks to be an effective way of setting breakpoints in a familiar manner. I may have to look at trying this at some point in the future.

You cannot programmatically switch to a different entity form in the Interactive Service Hub

It is sometimes useful to change the currently loaded form that a user is presented with depending on certain conditions. For example, if a user enters certain data within a Lead form to indicate the record should be treated as high priority, you may want a new form to be opened that contains additional fields, subgrids etc. that need to be completed in order to progress the record accordingly. Within the Xrm.Page.Ui reference, we have two methods that help us achieve this objective: formSelector.getCurrentItem, which returns the GUID for the currently loaded form, and formSelector.items, which returns a list of GUID’s for all forms that the current user has access to. The bad news is that, because these two methods are not supported in the mobile app, you will also be unable to use them within the ISH. This is likely due to the fact that, similar to Mobile Forms, only one form is presented to user when using the ISH, which is dictated by the form order and the users security permissions.

ISH forms do not contain a Ribbon

This may be one of the major reasons that prevent against an en masse adoption of ISH forms in the near future. One of the benefits of using the default CRM forms is the ability to modify the the CRM ribbon in order to add, remove or modify button behaviours across the application. This is great if you decide that you don’t want your users to have access to the Delete button, need to modify the order of the buttons to match the ones that are used the most or you need to setup a custom button that performs a web server call to an external system. Again, similar to the mobile application, there is no ribbon anywhere on the ISH, which means you may be missing out on key functionality going down this route.

ISH can only currently be used with a limited list of entities

If you are hoping to get your CRM setup to use ISH for your Sales related entities, then don’t get too carried away at this stage. You are currently limited to using ISH with a specific list of CRM entities. The full list, courtesy of our good friends again, is as follows:

  • Account
  • Contact
  • Case
  • All Activity Entities (System/Custom)
  • Social Profile
  • Queue Item
  • Knowledge Article
  • Custom Entities

Expect this to change in future, as one of the things that I have previously highlighted as part of Update 1/Service Pack 1 was the ability to add Feedback onto any entity within CRM, including custom ones. It would make sense that the Sales side of CRM gets some love and attention to include Leads, Opportunities etc. as part of ISH (so we may not even call it this if that happens!).

Conclusions or Wot I Think

It is clear that, whilst some of the headline benefits of using ISH are clear – visual experience, ability to drill down to individual records and efficient record filtering – , there are some very crucial and important technical limitations with the feature that need to be factored in before you decide to just completely migrate across to ISH. I would say that if your organisation has not been extensively customised to utilise form level scripting and other types of bespoke development work, then you can perhaps get away with making the jump. By contrary, you should be holding off and evaluating your existing customisations first to see if a) they are supported/unsupported by ISH or b) if there is some way to drop certain form scripting, ribbon customisations etc. in favour of using something default within CRM (for example, a Business Rule instead of a Jscript function). It could be that you can ditch a whole load of code that is not required as part of this exercise and instead utilise base functionality within CRM, something which is always preferable.

One thing I have been wondering about is the eventual aim with the ISH: is it intended that this will eventually replace the existing CRM user experience or will it continue to just be an alternative way of using CRM? It will be interesting to see how the feature is developed over the next couple of releases of CRM; one of the key indicators of this replacing the “old style” CRM forms is if we start to see all form scripting options made available in ISH and the introduction of the Ribbon.

In the meantime, make sure you do check out ISH at some stage, as the potential of setting up a visually attractive reporting and day-to-day application tool is huge. Just don’t let your Sales team see it yet, as you will end up disappointing them!