Archive

Archive for the ‘CRM 2011’ Category

[Step by Step] Using JSLint extension in VSCode

In this article, lets see how to Install and use JSLint extension in VSCode.

What is JSLint:

  • JSLint is a JavaScript program that looks for problems in JavaScript programs. It is a code quality tool.
  • JSLint takes a JavaScript source and scans it. If it finds a problem, it returns a message describing the problem.

Install JSLint extension in VSCode:

  • From the VSCode ‘Extensions’, search for ‘JSLint’ and Install.
  • Next, we need to install ‘jslint’ Globally by running ‘npm install -g jslint’ command from Terminal.
  • All the required files gets installed and Terminal looks as below.

Run JSLint on a JavaScript File:

  • Open the JavaScript file, which you want to validate in VSCode.
  • Open the Terminal and run ‘jslint {file_name}’ command. In my case, its ‘jslint HelloWorld.js’.
  • Script violations will be listed in Terminal as below.

🙂

Advertisement
Categories: JScript Tags: ,

Dataverse | Plugins | ILMerge Alternative | Shared Project

Role of ILMerge in Plugin Development:

If you are familiar with writing Plugins in Dataverse, chances are that you would have used ILMerge to merge the Assemblies.

In a typical Dynamics Plug-in development, we will have following .Net Class Library Projects.

  • Plugins.csproj
  • Plugins.Helper.csproj

When you compile above projects, you get two .dlls (i.e., Plugins.dll and Plugins.Helper.dll). As we can only deploy one .dll to Dataverse, we use ILMerge to merge both Plugins.dll and Plugins.Helper.dll in to one.

Is it recommended to use ILMerge in Plugin development? Answer is No. As per this Microsoft article ILMerge is not supported in Plugins development.

Now whats the alternative? Answer is Shared Projects.

Steps to use Shared Projects in Plug-in Development:

To explain the Shared Projects, I am going to build a simple Plugin project ‘Plugins.csproj’ with ‘PreAccountCreate’ class, which refers a ‘Shared’ Helper project ‘Plugins.Helper’.

  • Create a new C# class library project and add ‘PreAccountCreate’ class as below.
    • You can copy the code I’ve used from here.
  • Now lets add a ‘Shared’ Helper project which our Plugin project would refer.
  • Right click your Solution and click ‘New Project’.
  • Select a Project template of type C# ‘Shared Project’.
  • Give a Name to your ‘Shared Project’.
    • I’ve named it as ‘Plugins.Helper’.
  • ‘Plugins.Helper’ Shared Project, looks as below in the Solution Explorer.
  • Now add a Class file ‘AccountHelper.cs’ to the ‘Shared Project’.
  • I’ve added a simple function ‘GetAccountName()’ which returns ‘Microsoft India’.
  • To use the ‘Shared Project’ in our Plug-in project, right click ‘Plugins’ project and add ‘Reference’.
  • From ‘Shared Projects’, choose your project (i.e., Plugins.Helper in my case).
  • Once you referred the ‘Shared Project’ in your Plugin project, it looks as below.
  • Now its time to call ‘GetAccountName()’ from our ‘PreAccountCreate’ class.
  • Sign the Assembly.
  • Build the Plug-in project and you would get the ‘Plugins.dll’ in bin/Debug folder.
  • Go ahead and deploy the ‘Plugins.dll’ to Dataverse and register step using Plugin Registration Tool.

🙂

Categories: Plug-Ins Tags: , ,

Tip | Model Driven Apps | Client API | setSharedVariable and getSharedVariable

As we know Client-side scripting using JavaScript is one of the ways to apply custom business process logic for displaying data on a form in a model-driven app, In this article lets understand how to pass variables between event handlers (i.e., Different jScript functions registered as event handlers).

Lets understand this by first understanding the Form event pipeline.

Form event pipeline:

  • We can define up to 50 event handlers for each event. Each event handler is executed in the order that it is displayed in the Event Handlers section in the Events tab of the Form Properties dialog box.

setSharedVariable:

  • Sets the value of a variable to be used by a handler after the current handler completes.
  • Syntax : ExecutionContextObj.setSharedVariable(key, value);
    • Ex : ExecutionContextObj.setSharedVariable(“sharedAccountName“, formContext.getAttribute(“name”).getValue());

getSharedVariable:

  • Retrieves a variable set using the setSharedVariable method.
  • Syntax: var sharedVariable = ExecutionContextObj.getSharedVariable(key);
    • Xrm.Navigation.openAlertDialog({ text: ExecutionContextObj.getSharedVariable(“sharedAccountName“) });

🙂

[Dynamics CE] – Strange Plug-in issue due to the usage of global variables

December 26, 2018 Leave a comment

Other day, one of my colleagues reported a plug-in issue which could not be reproduced consistently. All the troubleshooting options (i.e., Plug-in Profiler, Tracing) had been used but was unable to found the root cause.

On close retrospection of code, we found out the usage global variables in Plug-in class file, which made the Plug-in ‘Stateful’.

Due to this, issue could not be reproduced when tested with Plug-in Profiler as it creates single Plug-in instance. Issue will only be reproduced when concurrent users instantiate plug-ins.

You have to make sure to create your Plug-in as ‘Stateless’ to avoid issues during concurrent Plug-in execution.

What is ‘Stateful’ Plug-in?

  • If the Plug-in ‘Execute’ method refer any global variable(s), makes the Plug-in ‘Stateful’.

public class CustomersVirtual : IPlugin{

// ‘context’ variable declared as Global
IPluginExecutionContext context = null;
EntityCollection results = new EntityCollection();
public void Execute(IServiceProvider serviceProvider) {
context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

if (context.MessageName.ToLower() == “retrieve”){
Entity customer = new Entity(“raj_virtualcustomer”);
customer[“raj_customersid”] = Guid.NewGuid();
customer[“raj_name”] = “ABC Corporation”;

//add it to the collection
results.Entities.Add(customer);
}

In the above Plug-in sample, variables ‘context’ and ‘results’ been defined as global and referred in ‘Execute’ method which makes it ‘Stateful’

What is ‘Stateless’ Plug-in:

  • If the Plug-in ‘Execute’ method, has its own local variables and does not refer any global variables make the Plug-in ‘Stateless’.

public class CustomersVirtual : IPlugin{
public void Execute(IServiceProvider serviceProvider){

// ‘context’ variable declared as Local variable
IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));

EntityCollection results = new EntityCollection();

if (context.MessageName.ToLower() == “retrieve”)
{
Entity customer = new Entity(“raj_virtualcustomer”);
customer[“raj_customersid”] = Guid.NewGuid();
customer[“raj_name”] = “ABC Corporation”;

//add it to the collection
results.Entities.Add(customer);
}

In this sample, variables ‘context’ and ‘results’ been defined as Local in ‘Execute’ method which makes it ‘Stateless’

Why ‘Stateless’ Plug-in is recommended?

  • As per the design, Dynamics platform caches plug-in class instances and hence the constructor is not called for every invocation of plug-in execution.
  • IPlugins should be stateless is that multiple system threads could execute the same, shared, plug-in instance concurrently.
  • This opens up members of classes that implement IPlugin to potential thread-safety issues which could lead to data inconsistency or performance problems.
  • Read-only, static, and constant members are inherently thread-safe and can also be used reliably within a plug-in class.

How the Dynamics platform Caches Plug-in?

  • For performance reasons, Dynamics DOES NOT dispose of the object after it completes execution.
  • Dynamics caches the object and calls Execute on the same object instance on the next activation of the plug-in.
  • Certain operations, such as changing a plug-in’s registration properties, will trigger a notification to the platform to refresh the cache. In these scenarios, the plug-in will be reinitialized..
  • This means that you need to be very careful when defining class-level variables in the plug-in class as multiple threads can execute the code at one time

Bottom line:

  • Don’t use Global variables in Plug-ins

Refer below articles for more insights:

🙂

Categories: CRM, Plug-Ins Tags: , ,

CRM 2011 (on-premise) – Querying Filtered views from CRM DB

We recently working on Data migration from CRM 2011 on-premise to Dynamics 365.

We got the CRM 2011 SQL DB back up, which we restored in our SQL server. But when we run query on ‘Filtered’ views we were getting 0 results.

FilteredView_1

Reason:

  • FilteredViews always run on CRM User context
  • The account I logged in to SQL server is not a CRM User/Service Account and hence Filteredview returning 0 results

Fix:

  • Before you querying ‘Filtered’ view, set the Context to CRM User using GUID
  • Below is the syntax:

— Set the Context

DECLARE @userid uniqueidentifier;
SET @userid = convert(uniqueidentifier, ‘123A81A3-89C3-E411-B6EF-441EA155CAB5’);
SET CONTEXT_INFO @userid;

–Execute the query
Select top 10 name,statecode,statecodename from FilteredAccount (nolock)

  • GUID used in above query is the valid CRM user’s GUID.
  • Now we should get the Accounts based on the Privilege and Access level of the User GUID we set the context with.

FilteredView_2

Site map changes after Activity Feeds solution import

In our CRM application we removed ‘Sales’ tab as per a business requirement.

 

Later as part of another requirement we installed ‘Activity Feeds’ managed solution in our application.

 

To our surprise ‘Sales’ tab resurfaced only with “What’s New” link.

Activity Feeds - Sitemap changes

Activity Feeds – Sitemap changes

Fix

To remove ‘Sales’ tab we followed below steps

  • Extract ‘Activity Feeds.zip’ managed solution folder
  • Open ‘Customizations.xml’ file
  • Removed ‘Sales’ sub area xml node and Save ‘Customizations.xml’ file
  • Zip the files and reimport the solution
  • It should remove ‘Sales’ tab

Note – You can include “What’s New” link on Workplace or other tabs required as per your business requirement.

🙂

Get the view name of main grid using JScript

January 29, 2014 Leave a comment

We got a requirement to Enable\disable ribbon button based on selected view.

View name

View name

We used JScript to disable the button by getting the selected view name.

Below is the script to get the selected view name of  Main Grid

var viewName = “”;

if (crmGrid && crmGrid.control) {

viewName = crmGrid.control.get_viewTitle();

}

🙂

Categories: CRM, JScript Tags: , ,

Table alias is not unique amongst all top-level table and join aliases – Exception

December 18, 2013 2 comments

Recently we upgraded from UR 8 to UR 13 and from then I was getting ‘Unexpected’ error when I was adding members to my ‘Dynamic Marketing list’ using ‘Advanced Find’ window.

Below is the error log from my Event viewer

Exception type: CrmException

Exception message: Table alias a_7f4fc1baff99e111bef200155dc87c59 is not unique amongst all top-level table and join aliases

This is a known issue  with UR 12 and would be resolved in UR 15.

Here is the link which has solution/workaround for the issue.

🙂

Why ‘RetrieveMultiple’ plug-in not firing when I choose ‘Activities’ roll-up view

November 26, 2013 Leave a comment

I had a plug-in registered  on ‘Activities’ (i.e., ActivityPointer) on ‘RetrieveMultiple’ message.

The Plug-in getting triggered when I open ‘Activities’ from any where (i.e., From ‘Advanced Find’, Sitemap on workplace area, Associated views of  all custom entities) except when I open an account and click on ‘Activities’ associated/roll-up view.

Reason

  • For ‘Accounts’, CRM out of the box provides a rollup view for activities. When you click on ‘Activities’ associated view, CRM uses ‘Rollup’ message instead of ‘RetrieveMultiple’.

Activities Rollup View

Activities Rollup View

  • This is the reason why the ‘Retrieve Multiple’ plug-in is getting ignored when you click on ‘Activities’ link.

Workaround

  • To fire a plug-in when user clicks on ‘Activities’ link from ‘Account’, we need to register a Plug-in on ‘Rollup’ message.
  • However ‘Rollup’ message will not be exposed by CRM (Refer below Plug-in registration tool screen). It needs DB level tweaking to get the message and register a Plug-in which is strictly UN-SUPPORTED

Roll up message unavailable

Roll up message unavailable

  • Refer article how to do it unsupported way.

🙂

Found more than one RibbonDiff entity – Error while publishing customizations

November 24, 2013 3 comments

Other day when I was trying to edit my ‘Account’ entity ribbon using ‘Ribbon Work Bench’ tool, I was getting ‘Found more than one RibbonDiff entity’ error at the time of publishing customization’s.

Refer the KB Article

Reason

  • One of the reason could be, In <RibbonDiffXml>  there might be more than one  element with same ‘Id’.
  • In my case, I had two <HideCustomAction> node with same ‘HideActionId’

Fix

To fix the issue I followed below steps

  • Create a solution with the affected entity and export
  • Extract the folder, open the “customizations.xml”
  • Go to <RibbonDiffXml> and check if any of the XML elements with same Id’s
  • Delete or Rename the duplicate XML elements
  • Save, Re-import and Publish the solution

Note –

If by following the above steps in ‘Fix’ does not solve the problem, try these steps

  • Take a backup of “customizations.xml” file
  • Now open the original ‘customizations.xml’ and clear the xmlelements in <RibbonDiffXml> section
  • Save, Re-import and Publish the solution

Now if you open crm application and open the entity, you don’t find old ribbon changes since we clear all xml elements in <RibbonDiffXml> section.

To get back old changes and fix the issue follow these final steps

  • Export the solution back
  • Open “customizations.xml” file and copy the <RibbonDiffXml> section file from backup file
  • Make sure you don’t have any elements with duplicate Id’s
  • Save, Re-import and Publish the solution

🙂