Using Color codes in Option Set Items – Dynamics CRM 2016

Dynamics CRM 2016 overwhelms customers and consultants alike. There is no denying the fact that indeed, this has been a giant step forward be in terms of user experience or the rich set of functionalities, especially for our on-premise customers who have made the leap from CRM 2015 to CRM 2016.

And among these big set of feature release, sometimes very subtle yet powerful changes gets overlooked. One of that is the availability of extra metadata attribute called ‘Color’ for an optionset field. Not sure how many of you noticed it, but CRM now comes with an additional option of specifying the color for each option item in the optionset.

image

So let’s see how this field can be used.

The first thing to notice here is that you can specify the color code for each of the option items in hexadecimal value. For example – I have taken here the priority optionset and added three different colors for the three option items

High – Red

Normal – Green

Low – Blue

image

image

image

I save and publish the customization changes. These colors will be actually used in the interactive service dashboards. If you are not aware of the interactive service hub for CRM 2016, you can view the MSDN Documentation for the same by following the below link.

https://www.microsoft.com/en-us/dynamics/crm-customer-center/user-s-guide-for-the-new-interactive-service-hub.aspx

I have customized the Dashboard for interactive service hub to show a bar chart of cases by priority. You can access the interactive service hub for your organization by typing in the url in the format

<organization url>/engagementhub.aspx

When I opened the engagement hub for my organization, I can see the chart displayed with the colors I specified for each of the High, Low and the medium values.

image

 

Isn’t it cool? Just thinking how can you use it more. Well if you have some external application which reads data from the CRM and shows some chart, you can probably read the optionset metadat, get the color code and render the chart with the same code in CRM.

Hope this helps!

Debug your web resources efficiently in Dynamics CRM

Sometimes the most simple stuffs are the most appreciated ones. The same goes about this topic. There is nothing very geeky or some advanced feature of Dynamics CRM that I am going to talk about here. Yet these simple techniques would help a lot in your day to day CRM development.

Here I am going to touch base on very simple ways to efficiently debug you webresources. Developing javascript webresources are very common in every CRM implementation and these techniques will save you lot of time. So before you go ahead, if you already know the power of developer tools that comes with our modern browsers, if you skip this topic.

As I come across multiple projects, I still find developers using the common technique of putting debugger; statement in the javascript code where they want to debug. Let’s find out the steps to enable debugging in a method using the traditional way.

  • Put the debugger statement where you would possibly want to debug
  • Publish the webresource in CRM
  • Open the Tools –Internet Option in IE Properties and then uncheck the checkbox – ‘Disable Script debugging’.
  • Relaunch the page and then the browser will prompt to choose the debugging engine
  • The developer selects visual studio instance (existing or new) and then all the associated scripts are loaded and then debugging continues.

The above procedure had multiple problems and the most common I faced is that Visual Studio hanged after sometime or IE restarted every now and then you are just drawn out of the flow where you were just about to decode your issue. Also many a times developers ended checking in the code in TFS missing out on commenting or removing all the debugger lines in the code and this code makes it to production.

Well you needed to do all this till sometime back. But why not leverage the wonderful Developer tools that comes with each browser now a days. Not only you can debug your webresources most efficiently but also can do a host of other things. So let’s explore it together.

I created a webresource here named ‘account.js’ and upload it in CRM.

image

The webresource is pretty simple. It contains a method ‘account_load’ from where the displayAlert function is called which displays the alert. The account_load method would be configured to be called from the form onload.

function account_load() {
    this.displayAlert();
}

function displayAlert()
{
    Xrm.Utility.alertDialog("Inside alert statement");
}

Now when you do open the account record, you would see the alert. So let’s say you are getting an error during the form on-load. Now let’s see how can you use developer tools to debug this.

While the record is open, press F12. I am using chrome here but you can use even IE and Mozilla.

The developer tools open. You can find you script from the left hand pane.

image

You have the entire javascript for your view here. Now on the line number in the code window just click where you need to the debugger. And you are done. Check for the screenshot below.

image

Now just refresh the record pressing F5 and then next time the debugger will stop at that position.

image

You can now press F10 to F11 to debug as you want or press on the arrow highlighted in the above screenshot to pass through the entire script. Wonderful isn’t it? No more putting debugger statements in the code.

Now say you want to find how your code executed and whether your code entered a particular execution block or not. The most popular way all this time has been using the window.alert method to identify the same. However after you go through what I will show you here now, I bet you will no longer need the alert methods.

You can now use the console.log methods to determine your code execution path. Just check for the code below.

function account_load() {
    console.log("entering form load.")
    this.displayAlert();
}

function displayAlert()
{
    console.log("inside display alert.");
    //Xrm.Utility.alertDialog("Inside alert statement");
}

Publish the webresource and simply open a new account record. However Once the record loads successfully, press F12. Once the developer tools load, just navigate to the console tab. All the messages that you wrote in the code through the console.log statements are displayed here.

image

As you can see, all the messages are displayed in the console. No longer annoying alerts and everytime clicking on that to get rid of it.

Thinking that’s all the developer tools brings to you. Off course not! If you are keen on exploring the Xrm Library and does not really want to mug up all the methods just like me, well you are in for a treat here.

Open a CRM record and open the developer tools. Go to the console and select the appropriate  frame. This is a very necessary step. Check for the screenshot below.

image

Normally it is main.aspx or page.aspx.

Now just type Xrm and you get the entire intellisense of your Xrm Scripts at your disposal.

image

Believe me, you can leverage this to test any code for your Xrm scripts. If you ask me, I first test my entire code in the console and then make changes in the webresource all at once without going through the grind of making a small change and publishing every time to check if it is working.

Hope this helps and saves you some time while you develop your webresources next time.

Why is CRM not performing full text search after installing Update 0.1–Dynamics CRM 2015 On-premise

Before you continue reading this post, make sure you are aware of the full text search enhancement for quick find that has been introduced with Dynamics CRM 2015 Update 0.1. In case you are not aware of this feature, you can refer to my another blog post – https://debajmecrm.com/2015/11/10/optimize-your-global-search-by-enabling-full-text-search-in-dynamics-crm/. This post would give you an idea about how to enable the feature in CRM and the benefits you get by enabling the same.

Now coming back to the topic, say you installed update 0.1 in your Dynamics CRM server. Next day you come to office, open your CRM to see the wonderful search working. You open your accounts grid and then search with a search phase. Alas, you see CRM is not performing the Full Text search as it should be. If you are in this situation don’t be upset. Once you finish reading this blog, you might end up with an optimistic feeling  of making it work.

So before we find out what can be the issue, let us make sure that CRM is not performing a full text search. For this open SQL profiler in your SQL server and then search for accounts with search phrase ‘test’ from your CRM UI. If your CRM would be using full text searches, the query would be something like below. See for the highlighted part

exec sp_executesql N’select
top 251 ( select count(1) from Account where ParentAccountId = "account0".AccountId ) as "HierarchyDataChildCount6dcd9e4c001441b09237d51a34853d55"
, "account0".Name as "name"
, "account0".AccountNumber as "accountnumber"
, "account0".Address1_Composite as "address1_composite"
, "account0".AccountId as "accountid"
, "account0".ParentAccountId as "HierarchyDataParentID6dcd9e4c001441b09237d51a34853d55"
, "account0".Address1_Line1 as "address1_line1"
, "account0".Address1_Line2 as "address1_line2"
, "account0".Address1_Line3 as "address1_line3"
, "account0".Address1_City as "address1_city"
, "account0".Address1_StateOrProvince as "address1_stateorprovince"
, "account0".Address1_PostalCode as "address1_postalcode"
, "account0".Address1_Country as "address1_country"
, "account0".ParentAccountIdName as "parentaccountidname"
, "account0".ParentAccountIdYomiName as "parentaccountidyominame"
from
Account as "account0"
where
[account0].[AccountId] in (
SELECT "account0".[Key] AS [AccountId] FROM ContainsTable([AccountBase], (EMailAddress1, AccountNumber, Name), @EMailAddress10) AS "account0") and (((("account0".StateCode = @StateCode0 and ("account0".AccountNumber not like @AccountNumber0 or "account0".AccountNumber is null) and ("account0".AccountNumber not like @AccountNumber1 or "account0".AccountNumber is null) and "account0".Name is not null)))) order by
"account0".Name asc
, "account0".AccountId asc’,N’@StateCode0 int,@AccountNumber0 nvarchar(200),@AccountNumber1 nvarchar(200),@EMailAddress10 nvarchar(200),@AccountNumber2 nvarchar(200),@Name0 nvarchar(200)’,@StateCode0=0,@AccountNumber0=N’2%’,@AccountNumber1=N’4%’,@EMailAddress10=N'((("test*" OR FORMSOF(FREETEXT, "test"))) OR ("test"))’,@AccountNumber2=N'((("test*" OR FORMSOF(FREETEXT, "test"))) OR ("test"))’,@Name0=N'((("test*" OR
FORMSOF(FREETEXT, "test"))) OR ("test"))’

Check for the FORMSOF method used by CRM for full-text search. If your CRM is not using this then it is not using the full text search.

We are not going to let CRM off just like that. If you are like me and wants to dig a little deep well you are in here. So let’s open your SQL Server here. Open your CRM Organization Database –> Storage –> Full Text Catalogs –> CRMFullTextCatalog.

image

Double click on this. The tables which are full text indexed will appear on the right hand pane of the popup window.

image

Here we can see that only two tables have been enabled for full text index. If CRM would have completed the full text search successfully, then you would find multiple tables enabled for full-text search. So the big question here. Would enabling the AccountBase table for full-text indexing manually make CRM to go for full text search? The answer is BIG NO. This is because CRM uses other set of tables to identify whether the full-text search should be used for quick find queries.

So what are the two tables. Let’s see.

The first table which is prime importance here is the EntityIndex table. This is the table where CRM maintains all type of indexes for an entity including the primary key index. Let run the below SQL query.

Select * From EntityIndex Where IndexType = 9 and Name = ‘AccountBase_FullText’.

Running this query on an organization database where Full Text search has been configured successfully would give you a result like the one shown below.

image

By default, CRM names each full text search in the format <entityschemaname>_FullText

The following are the notable columns for the table EntityIndex

IndexId Primary key of the table
Name The name of the index
EntityId The guid of the entity. you can get the entityid based on the schema name of the entity from the EntityView table
IsClustered Boolean to indicate if the index is clustered or not
IsUnique Boolean to indicate if it is Unique Key Index
IndexType The type of the index. 9 is the index for full text search.

 

Now where does CRM maintain the columns on which full text indexing should be performed? CRM maintains it in another table called IndexAttributes. Based on the IndexId of the EntityIndex table, let’s run a query on the IndexAttributes table.

image

As you can see from the above screenshot, the query returned 3 rows. The reason is that the quick find view of the customers contains only three columns. Only the columns in the quick find view which are of type text are enabled for full text search. A quick glance on the important fields of this entity.

AttributeId The guid of the attribute enabled for full text search
IndexId Reference of the IdexId from the EntityIndex table
IsQuickFindManaged Boolean to indicate if CRM will perform full text searches for this column.

So now you know fully from where CRM does all it’s magic.

Since you know the in and out of this now, let’s now understand the scenarios when full text search does not work even after enabling it through system settings.

  • The value for ‘enablequickfindoptimization’ is set to 0 for your organization. This setting is available in the Organization table of your organization database. You should set it to 1 to make full text searches work for your organization. You can edit the value of this field for your organization using the wonderful tool available in codeplex – https://orgdborgsettings.codeplex.com/
  • Make sure your CRM maintenance jobs which contains the Indexing management and Reindex All jobs ran in the last 24 hours. You can check the status of your maintenance jobs using the following tool – https://crmjobeditor.codeplex.com/
  • Last but not the least, if your CRM async server and CRM App server are different (which is for majority of the CRM deployments), remember to install Update 0.1 on all CRM app servers as well as CRM Async servers. Although this may sound silly, but recently I got multiple complaints from my customers saying that full text search was working great in the dev. environment (APP +  ASYNC on the same server), but not working in PROD. The reason is the administrator of their company installed the update only in the APP servers and not the async servers.

Hope this gives you an insight of CRM Full text search.

Till then you read one or more of my posts, happy CRM’ing.

{Tips & Tricks}–Show repeating content in Dynamics CRM 2016 word templates

Well, let me be very honest here. I hated to write this blog post. But to my surprise, I am finding lot of people wasting their valuable on this small stuff. So I thought, let me pen down this rather insignificant stuff so that it can help at-least someone stuck with the same issue.

I am not going to document here regarding the word template generation feature of Microsoft Dynamics CRM 2016. My personal favorite – http://crm.fueledbysleep.com/no-code/the-new-features-of-dynamics-crm-2016-how-to-use-them/#comment-3336 which explains both how you can use the word and excel templates to your advantage.

Here I am going to explain how to generate repeating content, for example – show all the emails related to an account.

First I download a template for the account entity. How to do it, you can find from the above post. As I am interested only in the emails, I have just included that relationship.

image

 

Now I insert a table. I wanted to include From address, to address and the subject of the email. So I create a table with the appropriate headers. I select a 3×2 table as I need an empty row after my header.

image

 

Now I select each of the three cells in the empty row of the above table and then insert appropriate fields. Another important point to note here is, if you want to display the From and To fields of the email, do not select the from and to. Instead select the fields – sender and torecipients. Otherwise the fields won’t display anything.

image

 

Now comes the important part. Select the entire row (all the cells of the row) using the cursor (do not select the table or the row from the table border)

Once the entire row is select, right click the relationship and then select Repeating as shown in the screenshot below.

image

 

It would look like something as below once you are done with the whole process. The biggest mistake people do here is select the entire table or select the entire row from the border of the table. If you do that, the table won’t be visible at all.

image

Save and upload the document template. To do this, please refer to the link I provided. Now once you view the template in the context of the account record, you can see all the emails.

image

 

Pretty layman stuff but hope it saves you some time.

Invoke your Custom Action from Dynamics CRM Web API–Dynamics CRM 2016

Continuing with my series of blog posts related to the wonderful Web API of CRM 2016, in this blog post, I will explain how to execute custom actions through Web API. No more use of creating complex SOAP queries from the client side to invoke your action. The wave of Web API is here to sweep off the old established complex rules.

Let’s create a custom action here. I name it TestAction for the account entity. Below is the screenshot for the same.

image

As you can see the, the Action is pretty simple. I have two input parameters for the action – ‘Subject’ and ‘Description’. All the action does is send an email with the Subject and Description populated from the input arguments of the action. I activate the action. Now let’s get dirty with the code to invoke this action from the client side.

var organizationUrl = Xrm.Page.context.getClientUrl();
var data = {
    "Description": "Test description",
    "Subject": "Invoking from Web API"
};

var query = "accounts(DE57510E-59A3-E511-80E4-3863BB35AD90)/Microsoft.Dynamics.CRM.new_TestAction";
var req = new XMLHttpRequest();
req.open("POST", organizationUrl + "/api/data/v8.0/" + query, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
    if (this.readyState == 4) {
        req.onreadystatechange = null;
        if (this.status == 200) {
            alert("Action called successfully");

        } else {
            var error = JSON.parse(this.response).error;
            alert(error.message);
        }
    }
};

req.send(window.JSON.stringify(data));

Let me explain the code here. Since the action is based on the account entity, I can invoke it only from the context of an account record. DE57510E-59A3-E511-80E4-3863BB35AD90 is the guid of the account record. Check carefully here. I am invoking my action using the fully qualified namespace of my action message – Microsoft.Dynamics.CRM.new_TestAction

Like I do all the time to test my code, this time also I open CRM in my browser and pull up the powerful developer tool’s console.

image

I press enter and CRM does the magic! I check my emails and this is what I get.

image

Never mind the two records created here. I was so excited that I ran the code twice. Smile

Similar to this, you can call your global actions also which are not bound to entity. Below would have been the request URL if new_TestAction would have been a global action.

https://xrmtr11.crm5.dynamics.com/api/data/v8.0/new_TestAction

Please note you do not need to use the full qualified namespace for calling a global action unlike the action bound to entity.

Hope this helps! Till you read one of my blog posts, happy exploring CRM 2016.

Re Arrange TabIndex from Left to Right in CRM forms

Chandana's CRM Blog

Generally, by default CRM provides tab order from top to bottom. But sometimes depending on the requirement or for professional look and feel we come across Left to Right order in CRM forms.

To change the default tab order use the following lines of code

function tabOrderLefttoRight() {

for (var i = 0; i < Xrm.Page.ui.controls.getLength() ; i++) {

var element = Xrm.Page.ui.controls.get(i);

if (element.tabIndex && element.tabIndex != “0”) {

if (element.className == ‘ms-crm-Hidden-NoBehavior’)

continue;

if (element.tagName == ‘A’) {

if (element.className != ‘ms-crm-InlineTabHeaderText’)

continue;

}

element.tabIndex = 1000 + (i * 10);

}

}

}

The above code runs well on IE 11 and for Chrome for CRM 2013 environment. For 2011 we need to get the length of the controls used in the form using crmForm. As it unsupported customization going forward we use Xrm attributes. Calll the above function on…

View original post 26 more words

Impersonate a user using the Microsoft Dynamics Web API in Dynamics CRM 2016

I have been exploring the Dynamics CRM Web API features and frankly speaking it never ceases to amaze me. So today I am going to explain how you can impersonate a user to create a record from the client side. Wondering how can we impersonate from the client side. After all, till this time, plugins were the privileged objects to do something in impersonation. Well, then Web API has come to shatter many establishments in the CRM society.

I have two users in my CRM system. System Administrator and my account.

image

I am going to login with the System Administrator account and then create an account on behalf of my account (Debajit Dutta).

Below is the code to do the same.

var organizationUrl = Xrm.Page.context.getClientUrl();
var data = { "name": "Sample Account – Impersonation Test" };

var query = "accounts";
var req = new XMLHttpRequest();
req.open("POST", organizationUrl + "/api/data/v8.0/" + query, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("MSCRMCallerID", "28888439-85AF-E511-80EB-3863BB35AD90");
req.onreadystatechange = function () {
    if (this.readyState == 4) {
        req.onreadystatechange = null;
        if (this.status == 200) {
            // do your stuffs

        } else {
            var error = JSON.parse(this.response).error;
            alert(error.message);
        }
    }
};

req.send(window.JSON.stringify(data));

Let me explain the code a bit here. Here I am creating a account named “Sample Account – Impersonation Test”. However I am creating the record under impersonation. The GUID of the person whom I am impersonating is passed as the MSCRMCallerID in the request header. “28888439-85AF-E511-80EB-3863BB35AD90” is the guid of the user – Debajit Dutta.

So how do I run the code? If you are thinking, a new webresource needs to be created and uploaded in CRM and then the code is to bee fired based on some event, I am not going to do nothing like that. After all we have the very powerful developer tools of modern browsers at our disposal. So why go the traditional way to try your piece of code?

I opened CRM in Chrome and then pull up the Developer tools in Chrome. In the console I copy-paste the above code.

image

I press enter and voila! the new account is created. Now If I pull up the record in Advanced Find. Below is the screenshot of the same.

image

So as you can see the Created by is the user whom I impersonated and the Created By Behalf is the user who actually performed the operation.

The power of Web API allows you to do this impersonation in just 10 mins or so and that too from the client side. Isn’t it great!

Hope this helps!