Friday 10 August 2018

Remove optionset values dynamically using Javascript



Remove Optionset Value or Two option set Value Using Javascript


Hi all,

In CRM community I read a question that how to remove the option from Two optionset field based on conditions.

Long back I tried to remove values from Optionset field but I never tried to remove from Two option set field.

So now I changed my code for Two option set as well.

Using this code, we can remove multiple values at a time.

So here is the code

var Seperator = ",";

function RemoveOptionsByText(Field, Options) {


    //------------------------------------------------------------------------
    // Parameters Field - Optionset field
    //              Options - Array or list of text of options to be removed (case insensitive)
    // Action Locates and removes the specified options
    // Returns true if successful, otherwise false
    //------------------------------------------------------------------------

    var result = false;

    if (Field!=null) {
        var obj = Xrm.Page.getControl(Field);
        var Text = new String();
        var chk = new String("");
        var ary;
        var i;

        Options = ListToArray(Options);
        if (Options != null) {
            for (var o = 0; o < Options.length; o++) {
                Text = Options[o];
                if (Text != null) {
                    Text = Text.toUpperCase();
                    ary = Xrm.Page.getAttribute(Field).getOptions();
                    for (i = 0; i < ary.length; i++) {
                        chk = new String(ary[i].text);
                        if (chk.toUpperCase() == Text) {
                            obj.removeOption(ary[i].value);
                            result = true;
                            break;
                        }
                    }
                }
            }
            if (!result && DEBUGGING) alert("No text matches found");
        }
        else {
            if (DEBUGGING) alert("No text provided for match in RemoveOptionsByText");
        }
    }
    return result;
}

function ListToArray(list) {

    //------------------------------------------------------------------------
    // Parameters list - delimited string or array
    // Action Converts list to an array
    // Returns array of items
    //------------------------------------------------------------------------

    if (!Array.isArray(list)) {
        if (list + "" == "") return null;
        list = list.toString();
        list = list.split(Seperator);
    }

    return list;
}

function OnLoad(){
// Your Condition
RemoveOptionsByText("new_testtwooptions","yes");   // Here I am removing Yes from Two options field
//RemoveOptionsByText("new_testtwooptions","no");   // Here I am removing No from Two options field
//RemoveOptionsByText("new_optionsetfield",["A","B"]);   // Here I am removing A,B Options from optionset field ()
}

Thursday 19 July 2018

Filter Activities based on users

Filter Activities based on User


                                Recently I got a requirement to filter emails in activities tab based on users. By default in Activities pane, it will show all emails regarding the current record. So there is no OOB functionality to achieve. And unfortunately, apply a custom filter on Activities pane using JavaScript also not possible as it's not a grid. So we need to register a Plugin on Retrieve Multiple.

How Query looks like?
                                
                              Here in Activities, we only will get Activity related information.so we need to Link related entity of ActivityParty. In this entity, we will get only two fields which are Participation Type and Party. Here Participation Type can be From/To/CC/BCC. This will be based on your requirement. Party is the MultiLookup which you can choose All Entity Records which entities allowing Emails in Communication & Collaboration section while creating an entity. This Acts as Activity Party.

                                By default, CRM will have a Plugin Step Retrieve Multiple. So either we can append our custom query or we can completely remove existing CRM query and add our custom query. But appending our custom query will be the best practice.

Here is the Query

QueryExpression qe = (QueryExpression)Context.InputParameters["Query"];
                    LinkEntity linkEntity = new LinkEntity("activitypointer", "activityparty", "activityid", "activityid", JoinOperator.Inner);

                    linkEntity.LinkCriteria.AddCondition(new ConditionExpression("partyid", ConditionOperator.Equal, Context.InitiatingUserId));

                    FilterExpression filter1 = new FilterExpression(LogicalOperator.Or);
                    //filter1.Conditions.Add(
                    filter1.Conditions.Add(new ConditionExpression("participationtypemask", ConditionOperator.Equal, 2));
                    filter1.Conditions.Add(new ConditionExpression("participationtypemask", ConditionOperator.Equal, 3));
                    filter1.Conditions.Add(new ConditionExpression("participationtypemask", ConditionOperator.Equal, 4));
                    linkEntity.LinkCriteria.AddFilter(filter1);
                    qe.LinkEntities.Add(linkEntity);
                    Context.InputParameters["Query"] = qe;
                   
As explained, the above query will retrieve activities where Participation Type will be either To/CC/BCC. I am showing emails to the user whether he involves any of the above participation types. And Party should be User and who is calling this Plugin. So who is new to CRM should care that while registering your step you need to select Run in Users context as Calling User.


Here is the full code:

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);
            QueryExpression qe = (QueryExpression)Context.InputParameters["Query"];
            AppendLog("Activity.Retrieve Multiple-Started");
            if (qe.EntityName == "activitypointer"&& Context.MessageName == "RetrieveMultiple")
            {
                FilterActivities(userService);
               
            }
            AppendLog("Activity.Retrieve Multiple-Finished");
        }


public void FilterActivities(IOrganizationService service ,IPluginExecutionContext Context)
        {
            try
            {
               
                if (Context.InputParameters["Query"] is QueryExpression)
                {

                    QueryExpression qe = (QueryExpression)Context.InputParameters["Query"];
                    LinkEntity linkEntity = new LinkEntity("activitypointer", "activityparty", "activityid", "activityid", JoinOperator.Inner);

                    linkEntity.LinkCriteria.AddCondition(new ConditionExpression("partyid", ConditionOperator.Equal, Context.InitiatingUserId));

                    FilterExpression filter1 = new FilterExpression(LogicalOperator.Or);
                    //filter1.Conditions.Add(
                    filter1.Conditions.Add(new ConditionExpression("participationtypemask", ConditionOperator.Equal, 2));
                    filter1.Conditions.Add(new ConditionExpression("participationtypemask", ConditionOperator.Equal, 3));
                    filter1.Conditions.Add(new ConditionExpression("participationtypemask", ConditionOperator.Equal, 4));
                    linkEntity.LinkCriteria.AddFilter(filter1);
                    qe.LinkEntities.Add(linkEntity);
                    Context.InputParameters["Query"] = qe;
                    return;
                }
            }
            catch (Exception ex)
            {
               
                throw;
            }
        }

Plugin step Details
Message Name: Retrieve Multiple
Event Pipe Line Stage: Pre-Operation
Primary Entity: Activity Pointer

Why Pre Create?

As I already mentioned, for every entity CRM will have to Retrieve Multiple Step and whenever we want to use advanced find then based on the query we passed, it will call the Plugin Step with the provided query. So before the operation of Plugin Step completed, we need to inject our query also. So this can be possible before the operation. So we need to register on Pre-Operation.

                Once we registered this Plugin and open any record which is having Activities Pane, you can see his related Activities only.


Hope it Helps!

Wednesday 21 February 2018

Console Application Service for Latest Versions

Retrieve service using the console in Dynamics 365 V9.0



While Retrieving service we will be getting an error in Dynamics 365 V9.0. To avoid that error, we need to add one additional line to our code for the Retrieve Service.

But What can be the issue?
Microsoft Introduced Transport Security Layer 1.2 (TSL 1.2) for SDK assemblies. So an updated version of CRM we are having TSL 1.2

.net Framework Version 4.6 and above will support TSL by default. While coming to lower FW versions we are getting connection issues.

What can be the solution?

Add the following line of code while retrieving service:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

And followed by the complete code here:
  public static IOrganizationService RetrieveService(Uri organizationURL, string userName, string password)
 {
   var url = organizationURL;
   ClientCredentials cre = new ClientCredentials();
   cre.UserName.UserName = userName;
   cre.UserName.Password = password;
   ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
   using (OrganizationServiceProxy proxy = new OrganizationServiceProxy(url, null, cre, null))
      {
         proxy.EnableProxyTypes();
         IOrganizationService service = (IOrganizationService)proxy;
         return service;
       }
   }