Duplicate detection in Microsoft Dynamics CRM Using a generic Plugin

Hi all,

Lot of times I used to write different plugins for duplicate detection,but got a thought of writing a generic plugin by passing the the parameters to check duplicates from Un Secure Config in Parameters.

Read the parameters passed from Un Secure Configurations:

I used a generic List for reading the parameters

List<string> parameters=new List<string>();

public CheckDuplicate(string unSecureConfig)
{
foreach (var item in unSecureConfig.Split(‘|’))
{
parameters.Add(item);
}
}

Design Query Expression:

Generic Query Expression is designed in this way

private QueryExpression getQueryExpression(Entity entity, string entityLogicalName, List<string> parameters)
{
QueryExpression query = new QueryExpression();
query.EntityName = entityLogicalName;
query.ColumnSet = new ColumnSet(true);
FilterExpression ft = new FilterExpression();
ft.FilterOperator = LogicalOperator.And;
foreach (var item in parameters)
{
if(entity.Contains(item))
{
if((entity.Attributes[item].GetType().Equals(typeof(Microsoft.Xrm.Sdk.OptionSetValue))) && ((OptionSetValue)entity.Attributes[item]).Value!=null)
{
int attributeValue=((OptionSetValue)entity.Attributes[item]).Value;
ft.AddCondition(new ConditionExpression(item, ConditionOperator.Equal, attributeValue));
}
else if((entity.Attributes[item].GetType().Equals(typeof(Microsoft.Xrm.Sdk.EntityReference))) && ((EntityReference)entity.Attributes[item]).Id!=null)
{
Guid attributeValue = ((EntityReference)entity.Attributes[item]).Id;
ft.AddCondition(new ConditionExpression(item, ConditionOperator.Equal, attributeValue));
}
else if((entity.Attributes[item].GetType().Equals(typeof(Microsoft.Xrm.Sdk.Money))) && ((Money)entity.Attributes[item]).Value!=null)
{
decimal attributeValue = ((Money)entity.Attributes[item]).Value;
ft.AddCondition(new ConditionExpression(item, ConditionOperator.Equal, attributeValue));
}
else if(entity.Attributes[item].ToString()!=null)
{
string attributeValue = entity.Attributes[item].ToString();
ft.AddCondition(new ConditionExpression(item, ConditionOperator.Equal, attributeValue));
}
}
}
query.Criteria = ft;
return query;

}
}

 

Use this Query Expression to retrieve duplicate records present in the system

Complete Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using System.Runtime.Serialization;
using System.ServiceModel;
using Microsoft.Xrm.Sdk.Query;

namespace duplicateDetection
{
public class CheckDuplicate:IPlugin
{
List<string> parameters = new List<string>();
public CheckDuplicate(string unSecureConfig)
{
foreach (var item in unSecureConfig.Split(‘|’))
{
parameters.Add(item);
}
}
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
if(context.InputParameters.Contains(“Target”) && context.InputParameters[“Target”] is Entity)
{
Entity entity = (Entity)context.InputParameters[“Target”];
string entityLogicalName = entity.LogicalName;
QueryExpression query = getQueryExpression(entity, entityLogicalName, parameters);
EntityCollection duplicates = service.RetrieveMultiple(query);
if(duplicates.Entities.Count>0)
{
throw new InvalidPluginExecutionException(“This record cannot be created since there are duplicates available in the system”);
}
}
}

private QueryExpression getQueryExpression(Entity entity, string entityLogicalName, List<string> parameters)
{
QueryExpression query = new QueryExpression();
query.EntityName = entityLogicalName;
query.ColumnSet = new ColumnSet(true);
FilterExpression ft = new FilterExpression();
ft.FilterOperator = LogicalOperator.And;
foreach (var item in parameters)
{
if(entity.Contains(item))
{
if((entity.Attributes[item].GetType().Equals(typeof(Microsoft.Xrm.Sdk.OptionSetValue))) && ((OptionSetValue)entity.Attributes[item]).Value!=null)
{
int attributeValue=((OptionSetValue)entity.Attributes[item]).Value;
ft.AddCondition(new ConditionExpression(item, ConditionOperator.Equal, attributeValue));
}
else if((entity.Attributes[item].GetType().Equals(typeof(Microsoft.Xrm.Sdk.EntityReference))) && ((EntityReference)entity.Attributes[item]).Id!=null)
{
Guid attributeValue = ((EntityReference)entity.Attributes[item]).Id;
ft.AddCondition(new ConditionExpression(item, ConditionOperator.Equal, attributeValue));
}
else if((entity.Attributes[item].GetType().Equals(typeof(Microsoft.Xrm.Sdk.Money))) && ((Money)entity.Attributes[item]).Value!=null)
{
decimal attributeValue = ((Money)entity.Attributes[item]).Value;
ft.AddCondition(new ConditionExpression(item, ConditionOperator.Equal, attributeValue));
}
else if(entity.Attributes[item].ToString()!=null)
{
string attributeValue = entity.Attributes[item].ToString();
ft.AddCondition(new ConditionExpression(item, ConditionOperator.Equal, attributeValue));
}
}
}
query.Criteria = ft;
return query;

}
}
}

Register the plugin in Pre-Operation of create and pass the parameters from Un secure configuration

Hope this helps 🙂

 

Hide Sub Grid ‘+’ button in Microsoft Dynamics CRM

Hi Folks,

We generally get these scenario lot of times in our requirement as hiding “+” button in Sub Grid.

We can achieve this in two ways .

Using un supported way in javascript and hiding the element :

http://”/webresources/new_Jquery.js”

$( document ).ready(function() {
if (parent.document.getElementById(“subgridname_contextualButtonsContainer”) != null ) {

parent.document.getElementById(“subgridname_contextualButtonsContainer”).style.display=’none’;}

});

Here subgrid name need to be replaced by your subgrid name

Ribbon Work Bench 2016 :

if you didn’t download Ribbon Work Bench you can download it from here Click Here .

Capture

Note : Hiding the + button does not mean users cannot create new records, allowing or forbidding users to create new records should  be configured in their security roles.

 

Hope this helps 🙂

Use Of OData in Javascript in Microsoft Dynamics CRM

Hi Friends,

This will be oldest post you will find in google regarding odata usage in Microsoft Dynamics CRM , but i feel this will give lots of information regarding Odata. Although Microsoft has introduced WEB API in javascript in its latest update, till we can write our queries using OData .

XMLHttpRequest object :

Server requests from browser are made through XMLHttpRequest Object . JavaScript requests use XMLHttpRequest use two functions

  • Send Request – to send request to browser
  • Call Back – to get response browser .

XMLHttpRequest  object has capabilites to send requests to browser and call back (response) requests from browser .

Often we use jquery functions to write these queries , but Microsoft has recommended to user not to use Jquery methods for Querying data . (Here Jquery.Ajax is referred as $.Ajax which uses XMLHttpRequest available in the browser for querying the data from server )

PUT,DELETE,MERGE  requests are noted as POST request .

RETRIEVE request are stated as GET request.

To support versions of Windows Internet Explorer prior to Internet Explorer 7, use the following function to get the XMLHttpRequest object.

//Retrieves XMLHttpRequest object
function GetRequestObject()
{
if (window.XMLHttpRequest)
{
return new window.XMLHttpRequest;
} else
{
try {
return new ActiveXObject(“MSXML2.XMLHTTP.3.0”);
} catch (ex) {
return null;
}
}
}

 

Access the server URL :

The first thing to do when you start to use the ODATA endpoint with JavaScript is establish the URL to the organization root URL

var serverUrl = Xrm.Page.context.getClientUrl();

Create OData Query :

It can be created manually or using CRM rest builder tool

Sample :

var userRolesQuery = “/RoleSet?$top=1&$filter=RoleId eq guid'” + RoleId + “‘&$select=Name”;

Example : Retrieve Security Roles of Logged in User in Microsoft Dynamics CRM

//Main method to retrive all user roles

function getAllUserRoles()
{
var Roles = Xrm.Page.context.getUserRoles();
for (var i = 0; i < Roles.length; i++)
{
var RoleId = Roles[i];
//Query designed by using Odata
var userRolesQuery = “/RoleSet?$top=1&$filter=RoleId eq guid'” + RoleId + “‘&$select=Name”;
var role = null;
role = GetRolesRequest(userRolesQuery);
var RoleName = role[0].Name;

alert(“Role ID=” + RoleId + ” Role Name=” + RoleName);
}
}

NOTE : Xrm.Page.context.getUserRoles() returns an array of GUIDs of roles  that the User currently has

// OData Request :

function GetRolesRequest(query)
{
var serverUrl = Xrm.Page.context.getClientUrl();

var oDataEndpointUrl = serverUrl + “/XRMServices/2011/OrganizationData.svc/”;
oDataEndpointUrl += query;

var service = GetRequestObject();

if (service != null) {
service.open(“GET”, oDataEndpointUrl, false);
service.setRequestHeader(“X-Requested-With”, “XMLHttpRequest”);
service.setRequestHeader(“Accept”, “application/json, text/javascript, */*”);
service.send(null);

var retrieved = JSON.parse(service.responseText).d;

var results = new Array();
for (var i = 0; i < retrieved.results.length; i++) {
results.push(retrieved.results[i]);
}

return results;
}
return null;
}

 

Retrieve XMLHttpRequest  object :

//Retrieves XMLHttpRequest object
function GetRequestObject()
{
if (window.XMLHttpRequest)
{
return new window.XMLHttpRequest;
} else
{
try {
return new ActiveXObject(“MSXML2.XMLHTTP.3.0”);
} catch (ex) {
return null;
}
}
}

Hope this helps 🙂

On Premise Installation of Microsoft Dynamics CRM 2015/2016 Server

Hi folks,

We all get lots of information for setting up Micrsoft Dynamics CRM 2015/2016 server in on premises.In this post, i will explain clearly about setting up Microsoft Dynamics CRM 2015/2016 server on premises.

Active Directory setup on Windows Server 2012 :

  1. Open the Server Manager from the task bar.
  2. From the Server Manager Dashboard, select Add roles and features.

    This will launch the Roles and Features Wizard allowing for modifications to be performed on the Windows Server 2012 instance.

  3. Select Role-based or features-based installation from the Installation Type screen and click Next.
  4. The current server is selected by default. Click Next to proceed to the Server Roles tab.

     

  5. From the Server Roles page place a check mark in the check box next to Active Directory Domain Services. A notice will appear explaining additional roles services or features are also required to install domain services, click Add Features.
  6. Review and select optional features to install during the AD DS installation by placing a check in the box next to any desired features, and then click Next.Capture 
  7. Review the information on the AD DS tab and click Next.

     

  8. On the Confirm installation selections screen, review the installation and then click Install.

Configure Active Directory:

Once the AD DS role is installed the server will need to be configured for your domain.

  1. If you have not done so already, Open the Server Manager from the task bar.
  2. Open the Notifications Pane by selecting the Notifications icon from the top of the Server Manager. From the notification regarding configuring AD DS, click Promote this server to a domain controller.Capture.PNG
  3. From the Deployment Configuration tab select Add a new forest from the radial options menu. Insert your root domain name into the Root domain name(EX:CONTOSO.com) field, and then click Next.
  4. The system checks to ensure all necessary prerequisites are installed on the system prior to moving forward. If the system passes these checks, proceed by clicking Install.

Install SQL SERVER on Windows Server 2012 :

If you haven’t already downloaded SQL Server 2012 Express, you can get it from Microsoft here.

Step 1.
To begin, launch the install program and choose the top option to install a new stand-alone installation.

Capture.PNG

Step 2.
Read and accept the license agreement and click next. At this point you can choose the features that you want to install. You can also change the install folder if you do not want to install to the default location.

Click Next to continue.

Capture

Step 3.
Now you can configure the SQL instance. If this is the first instance of SQL Server on your computer, you probably want to change this setting to Default instance.  If you already have another instance of SQL Server, you will want to use Named Instance and give it a name.

Click Next to continue.

Capture

Step 4.
The next step is server configuration. From here you can change the Windows services associated with this instance of SQL Server. You can keep the defaults here unless you want to specify different user accounts for the services. You can also change the default collation settings if you are not in the United States.

Click Next to continue.

Capture.PNG

Step 5.
Now we come to the Database Engine configuration. On the Server Configuration tab you can select whether SQL Server will only authenticate using Windows accounts or you can choose Mixed Mode which will allow Windows accounts and SQL accounts

Capture

Step 6.
On the Data Directories tab you can change the locations of various files that SQL will use. Depending on your server configuration and the load that will be put on SQL, you may want to put the database and log folders on separate drives. For most people, you can leave the default values.

Click Next to continue.

Capture

Step 7.
The next step configures Reporting Services. Set this to Install Only if you don’t need reporting services or may need them in the future.  You can always go back and configure it later.

Click Next to continue.

Capture

Step 8.
On the Error Reporting step, you can choose whether or not you would like to send error reports to Microsoft to help them improve future releases of SQL server.

Click Next to continue.

Capture

At this point, SQL server will install on your computer.  This could take a while to complete depending on the computer you are using.

Capture

Once the installation has completed, you will receive a screen showing the details of what was completed and if there were any problems.

Capture

If everything completed successfully, you can close the window and begin using your new copy of SQL Server 2012 .

Make Sure these services are running fine, if not open services.msc and start the services.

Capture

Install Microsoft Dynamics CRM 2015 :

If you haven’t already downloaded  Dynamics CRM 2015 Server you can get it from Microsoft here.

Launch the installation wizard :

Capture

Step 2:

Capture

Make sure these updates will not create any hindrances in the system and Click next.

Capture

Microsoft provides 90 days free trial for on premises installation . you can get the key  here for trial version Evaluation Key .

Install Required Components:-

If Setup detects that components are missing, the Install Required Components page appears.

Note :- If you are prompted to restart the computer, do so, and then start Setup again

Capture.PNG

Capture

Either accept the default location or enter a different file installation location, and click on Next.

Capture

Select all roles to install

Capture

Specify Deployment Options page, select the name of the computer that is running SQL Server to use the deployment box, type or select the instance of Microsoft SQL Server that will be used to store the Dynamics CRM database (MSCRM_CONFIG)

Capture

Click on Browse to display your Active Directory structure. Select the location where you want the Microsoft Dynamics CRM organizational unit to be installed, click on OK, and click on Next. Microsoft Dynamics CRM security groups are  created in this organizational unit.

Capture

Specify Service accounts :

Capture

 

On the Select a Web Site page, click Create a new Web site or click Select a Web Site and select a website from the list. By default, Setup will use the default website.

When you select the Create a new Web site option, Setup creates a new website for Microsoft Dynamics CRM. You can specify the following option:

Port Number: Type the TCP port number that Microsoft Dynamics CRM clients will use to connect to the Microsoft Dynamics CRM Server 2015. The default port number is 5555. Click on Next

Capture

Specify the Organization Settings:-

On “Specify the Organization Settings” page, specify the following information.

1.   In the Display Name box, type the name of your organization.

2.   In the Unique Database Name box, you can keep the name that is automatically generated or you can type a unique name that must be limited to 30 characters. Spaces and extended characters are not allowed.

3.   Under ISO currency code, click Browse, select the ISO currency code that you will use as the base currency for the organization in the list, and then click OK.

You can change the currency’s symbol, name, or precision.

4.   In the SQL collation list, keep the default selection or select a different database collation that the organization database will use to sort and compare data characters.

Important:-

After Setup is complete, you cannot change the database collation, base ISO currency code, or the organization unique name. However, you can change the base currency name and base currency symbol.

Capture

On the Specify Reporting Services Server page, type the Report Server URL. Make sure that you use theReport Server URL, not the Report Manager URL.

To verify that you are using the correct URL, in a browser, type the Report Server URL as the address.

Capture

This page is a summary of all requirements and recommendations for a successful installation. Errors must be resolved before installation can continue. If no errors or only warnings appear, you can continue with the installation. To do this, click on Next

Capture

Capture

Click on install

Capture

Installation take awhile to complete and setup the Reporting extensions .

Here is an excellent video tutorial for Setting up Dynamics CRM 2015  Video

Hope this helps  🙂

 

 

Assign owner of a record in Microsoft Dynamics CRM using C#

Hi all,

There are few  scenarios in Microsoft Dynamics CRM where we come across to assign the owner of a record pro-grammatically using C# to achieve the business requirement.

Recently i came across a scenario from my client where i need to assign the owner of a Manufacturer(User/Team level entity) based on the channel(Lookup) in Microsoft Dynamics CRM.

In order to achieve this , Microsoft has provided us with AssignRequest class in Microsoft Dynamics CRM.

Assign Request Class :

AssignRequest assign = new AssignRequest
    {
        Assignee = new EntityReference("systemuser",
            new Guid("userguid")),
        Target = new EntityReference("TargetEntity",
            "TargetentityrecordGuid")
    };


// Execute the Request
service.Execute(assign);

Sample Code :

AssignRequest assign = new AssignRequest
    {
        Assignee = new EntityReference("systemuser",
            new Guid("9245fe4a-d402-451c-b9ed-9c1a04247482")),
        Target = new EntityReference("new_manfacturer",
           new Guid("8245fe4a-d402-451c-b9ed-9c1a04247482"))
    };


// Execute the Request
service.Execute(assign);

Hope this helps 🙂

 

Usage of “SHARED VARIABLES” in Microsoft Dynamics CRM Plugins

Hi Friends,

Here come my new post regarding the usage of shared variables in Microsoft Dynamics CRM Plugins . This is not new topic in plugins , here are few thoughts about them because most of us ignore them while using in Plugins.

In order to explain this, i hope all of us know about ASP.Net session concept . Sessions are also used for storing data and using the same data in all the forms in entire application.Here session gets disposed once the application is closed.

In the same way , shared variables are used for storing the data in one plugin and use the stored data in different plugin . But the main limitations comes here is we need to register the plugin on same entity.

Limitations Of Shared Variables :

  • Data can be passed from plugin that is registered on Pre-Operation to plugin registered on Post Operation. Vice-versa is also not possible
  • Data can be passed between different plugins on the same entity

Creation of a shared variable Pre-Operation Plugin :

Context.SharedVariables[“Key”] = Value ;

or

Context.SharedVariables.Add(“Key”,Value);

Here context is IpluginExecutionContext in Plugins in Microsoft Dynamics CRM.

Usage of a shared variable in Post Operation  Plugin :

//its always better to check whether the key presents or not

if(Context.SharedVariable.ContainsKey(“Key”)

{

string value=Context.SharedVariable[“Key”].toString();

}

Here context is IpluginExecutionContext in Plugins in Microsoft Dynamics CRM.

Sample helper Code :

Pre-Create Account Plug-in

if (context.InputParameters.ContainsKey(“Target”) && context.InputParameters[“Target”] isEntity)
{
Entity target = context.InputParameters[“Target”] as Entity;
if (target != null)
{
// some wacky data validation
string city = target.GetAttributeValue<string>(“address1_city”) ?? string.Empty;
int numEmployees = target.GetAttributeValue<int>(“numberofemployees”);
int accountCategory = target.GetAttributeValue<int>(“accountcategorycode”);

// city is auckland, numEmployees > 100, account category is preferred customer
bool updateRelated = city.Equals(“Auckland”,StringComparison.InvariantCultureIgnoreCase) && numEmployees > 100 && accountCategory == 1;
context.SharedVariables.Add(“updatedRelated”, updateRelated);
}
}

Post-Create Account Plug-in

if (context.InputParameters.ContainsKey(“Target”) && context.InputParameters[“Target”] isEntity)
{
Entity target = context.InputParameters[“Target”] as Entity;
if (target != null)
{
if (context.SharedVariables.ContainsKey(“updatedRelated”))
{
bool updateRelated = (bool)context.SharedVariables[“updatedRelated”];
if (updateRelated)
{
// additional logic to update related records of the Account
}
}
}
}

This helps in building complex plugins without usage of hidden fields in Microsoft Dynamics CRM

Hope this helps 🙂