Thursday, September 19, 2013

Capitalize First String Character of a word in Text Field of Dynamics CRM 2011

So, One of the Post in LinkedIn asking if anyone can help with a Script that can Capitalize First String Character of a word in Text Field of Dynamics CRM 2011.

For eg. If i have a custom Full Name Field or Address filed. If User enters like 1107 medowville lane,
The script should automatically converts it to Pascal Casing like, 1107 Medowville Lane.

I thought to give it a try and here is the full functional code.

function ConvertFirstCharToCaps()
{
var attribute = Xrm.Page.getAttribute("new_address"); // Change the Schema Name here

if(attribute != null)

var str = attribute.getValue();
    var pieces = str.split(" ");
    for ( var i = 0; i < pieces.length; i++ )
    {
        var j = pieces[i].charAt(0).toUpperCase();
        pieces[i] = j + pieces[i].substr(1);
    }

Xrm.Page.getAttribute("new_address").setValue(pieces.join(' '));
 
}

It can be converted to Parametrized Function, but here i am just giving an idea how this code can work on each field.

Hope this will help, Please change the Attribute name as per your Attribute Schema Name.

Thanks.

Wednesday, July 24, 2013

Prevent Users to Delete the Task if "Owner" of the Task is not the "Created by" of the Task using Plug-in in Dynamics CRM 2011

Requirement :  Prevent Users to Delete the Task if "Owner" of the Task is not the "Created by" of the Task using Plug-in in Dynamics CRM 2011.
On click of Delete button on Ribbon from anywhere Form, Subgrid, HomeGrid, if the Task "Owner" is not Same as Task "Created By" then Owner should be prevented from Deleting the Task with a User Friendly Message.
Implementation:
The Complete Code for the Plug-in to prevent an Owner to Delete the Task:

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Diagnostics;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.CSharp;
using System.Data;
using System.Runtime.Serialization;
using Microsoft.Crm.Sdk.Messages;
namespace TaskDeleteCheck
{
    public class PreventTaskDeletion : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            if (context.PrimaryEntityName == "task")
            {

                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is EntityReference)

                {
                    if (context.PreEntityImages.Contains("PreImage"))
                    {

                        Entity taskentity = (Entity)context.PreEntityImages["PreImage"];

                        EntityReference owneridLookup = (EntityReference)taskentity.Attributes["ownerid"];
                        EntityReference createdbyLookup = (EntityReference)taskentity.Attributes["createdby"];

                        if (owneridLookup.Id != createdbyLookup.Id)

                        {
                           throw new InvalidPluginExecutionException("This task is Created by : " + createdbyLookup.Name + " ,  User : " + owneridLookup.Name + " is not allowed to Delete the Task.");
                        }
                    }
                }
                else
                {
                    throw new InvalidPluginExecutionException("Activity should be task.");
                }

            }


        }

    }
}

The Plugin has to use Pre-Image to compare the values of the fields before transaction happens in the Database.

Now the Registration Process of Plug-in:


Open the Plugin registration Tool, Select your Organization, Log as Admin user (Or if any user has granted permission). 


1. Register New Assembly by browsing your dll.

2. You have to Register steps for the plugin on Delete step.
3. Register Pre-Image for the above step.





Once done, you are now Ok to test your business scenario,

Following are the screen shots, on Single Task and Multiple Tasks Closure Process from the CRM Landing Page (In My case Dashboard):

Single Task Selected:



Multiple Selection of Task:




Delete from the Ribbon Button the Task Form:





That's All.

Thank You for looking at my post.

Cheers!!!

Sunday, July 21, 2013

Prevent Users to Mark Complete or Close the Task if "Owner" of the Task is not the "Created by" of the Task using Plug-in in Dynamics CRM 2011

Requirement :  Prevent Users to Mark Complete or Close the Task if "Owner" of the Task is not the "Created by" of the Task using Plug-in in Dynamics CRM 2011.
On Click of Mark Complete on Ribbon button from anywhere in CRM Webpage (Form, Subgrid, HomeGrid), if the Task "Owner" is not Same as Task "Created By" then Owner should be prevented from Mark the Task Complete or Close with a User Friendly Message and and also a custom field on Task form called "Able to Mark complete" if the value of the Check box is true (Yes) then to override this requirement, i mean user can Mark Complete or Close.
Implementation:
First Create a Javascript to control the enabling and disabling of "Able to Mark complete" field on the Update form of Task. This field will be enabled for Creator of the Task on Create or Update form, but if the Owner of the Task is not the Creator of the Task then this field should be prevented to update on Update form of Task entity. Here is the JavaScript code to do so (I am avoiding the step to Add the JavaScript as web-resource and Attaching the code to Task form).
function DisableAbleToCompleteField()
{

var  formType = Xrm.Page.ui.getFormType();

   if (formType == 2)
   {
      var userid = Xrm.Page.context.getUserId();
      var creatorlookup = Xrm.Page.getAttribute("createdby");
      if (creatorlookup!= null)
      {
         var creatorlookupvalue = creatorlookup .getValue();
         if (creatorlookupvalue != null)
         {
              var creatorid = creatorlookupvalue[0].id;
          }
       }
                if (userid == creatorid) 
                  Xrm.Page.getControl("new_abletomarkcomplete").setDisabled(false);
           else       
                  Xrm.Page.getControl("new_abletomarkcomplete").setDisabled(true);
          
    }   else        
 Xrm.Page.getControl("new_abletomarkcomplete").setDisabled(false);
}

The Complete Code for the Plug-in to prevent an Owner to Mark Complete or Close the Task:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Diagnostics;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.CSharp;
using System.Data;
using System.Runtime.Serialization;
using Microsoft.Crm.Sdk.Messages;

namespace TaskClosurePermissionPlugin

{
    public class TaskClosure : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            if (context.PrimaryEntityName == "task")
            {

                if (context.InputParameters.Contains("EntityMoniker") && context.InputParameters["EntityMoniker"] is EntityReference && context.Depth < 2)

                {
                    if (context.PreEntityImages.Contains("PreImage"))
                    {

                        Entity taskentity = (Entity)context.PreEntityImages["PreImage"];

                        EntityReference owneridLookup = (EntityReference)taskentity.Attributes["ownerid"];
                        EntityReference createdbyLookup = (EntityReference)taskentity.Attributes["createdby"];
                       
                        if (owneridLookup.Id != createdbyLookup.Id)
                        {
                            if (taskentity.Contains("new_abletomarkcomplete") && !taskentity.GetAttributeValue<bool>("new_abletomarkcomplete"))
                            {
                                throw new InvalidPluginExecutionException("This Task is Created by : "+createdbyLookup.Name+" ,  User : "+owneridLookup.Name +" is not allowed to Mark Complete or Close the Task.");
                            }
                        }
                    }
                }
                else
                {
                    throw new InvalidPluginExecutionException("Activity should be Task.");
                }

            }


       }

    }
}

The Plugin has to use Pre-Image to compare the values of the fields before transaction happens in the Database.
Now the Registration Process of Plug-in:
Open the Plugin registration Tool, Select your Organization, Log as Admin user (Or if any user has granted permission). 
1. Register New Assembly by browsing your dll.
2. You have to Register steps for the plugin on SetState and SetStateDynamicEntity both steps.
3. Register Pre-Image for both Steps.


Once done, you are now Ok to test your business scenario,

Following are the screen shots, on Single Task and Multiple Tasks Closure Process from the CRM Landing Page (In My case Dashboard):

Single Task Selected:



Multiple Selection of Task:


Mark Complete from the Task Form:


That's All.

Thank You for looking at my post.

Cheers!!!



Tuesday, July 16, 2013

Validting phone number to US Format in Dynamics CRM 2011

Requirement: The phone number field should accept only 10 digits and should format in US phone number format (ex: XXX-XXX-XXXX)
This requirement can be completed with some java script:
// Function To validate the Mobile Phone field
function validateMPhone()
{
var phone = Xrm.Page.getAttribute("new_mobilephone").getValue();
var sTmp = phone.replace(/[^0-9]/g, "");
phoneRegex = /^\d{10}$/;

if( !sTmp.match( phoneRegex ) )
{
event.returnValue = false;
alert("Phone must contain 10 numbers.") ;
Xrm.Page.getAttribute('new_mobilephone').setValue('');
}
else
{
var sTmpClean =  "(" + sTmp.substr(0, 3) + ") " + sTmp.substr(3, 3) + "-" + sTmp.substr(6, 4);
Xrm.Page.getAttribute("new_mobilephone").setValue(sTmpClean);
}
}

Here is the step by step procedure:
1. Create a javascript web resource in the given solution .
2. Click the Text editor button and copy the above code in there.
3. Go to the Field properties of the field you want to validate.
4. Click on "Event" tab.
5. Under 'Form Library' Click on "Add" tab and  add the web resource.
6. In the Event Handelers, Select 'OnChange'  for the event and then click 'Add'.
7. Add the Function name validateMPhone and click on OK.
8. Publish the Solution.
When you enter a phone number which is not equal to 10 digits you will receive a message box and clicking 'Okay'.
The focus will be in the Phone field and the field would be cleaned up.

Display label of option set based on value

Display label of option set based on value


string GlobaloptionsetText = GetCRMOptionSetLabel(service, entity.LogicalName, "new_rating", irating);


   private string GetCRMOptionSetLabel(IOrganizationService service, string entityname, string optionsetname, int value)
        {
            Microsoft.Xrm.Sdk.Messages.RetrieveAttributeRequest reqOptionSet = new Microsoft.Xrm.Sdk.Messages.RetrieveAttributeRequest();
            reqOptionSet.EntityLogicalName = entityname;
            reqOptionSet.LogicalName = optionsetname;
            Microsoft.Xrm.Sdk.Messages.RetrieveAttributeResponse resp = (Microsoft.Xrm.Sdk.Messages.RetrieveAttributeResponse)service.Execute(reqOptionSet);
            Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata opdata = (Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata)resp.AttributeMetadata;
            var option = opdata.OptionSet.Options.FirstOrDefault(o => o.Value == value);

            return option.Label.LocalizedLabels.FirstOrDefault().Label;
        }

Copy Records from an entity to another entity through Plugin in Dynamics CRM 2011

Copy Records from an entity to another entity through Plugin in Dynamics CRM 2011
Requirement: Suppose you have to copy a record from one entity another, Lets say you have one custom entity called prospect with few attributes like Pipelinestatus, Rating, Firstname, Lastname. And you want to convert this Prospect Record to Lead means a new record in Lead entity copying over the all the attributes value from Prospect to Lead.
Following is the Plugin that can help you to create a copy of record:
Etity lead = new Entity("lead");

ColumnSet cols = new ColumnSet();
                                                                                 cols.AddColumns(new string[] { "new_pipelinestatus", "new_rating", "new_lastname", "new_firstname", "new_businessphone", "new_addressstreet1", "new_city", "new_stateprovince", "new_zippostalcode", "new_updatecounter" });

 entity = service.Retrieve("new_prospect", entity.Id, cols);

string status = "";
int irating = 0;
int count = 0;
if (entity.Attributes.Contains("new_pipelinestatus"))
 {
  //rating Please Select One=0,10%=1,20%=2,30%=3,40%=4,50%=5
irating = Convert.ToInt16(((OptionSetValue)entity.Attributes["new_rating"]).Value.ToString());
status = ((OptionSetValue)entity.Attributes["new_pipelinestatus"]).Value.ToString();
count = Convert.ToInt16(entity.Attributes["new_updatecounter"]);
count = count + 1;
//status P=1,L=2,C=3
   if (status == "1")
         {
  throw new InvalidPluginExecutionException("PipelineStatus Should be L or C to convert to Lead ");
           }
  if (irating == 0 || irating == 1)
         {
       throw new InvalidPluginExecutionException("Rating Should be greater than 10 To convert to Lead ");
          }
       }                         
  string GlobaloptionsetText = GetCRMOptionSetLabel(service, entity.LogicalName, "new_rating", irating);

                                            
if (entity.Attributes.Contains("new_lastname"))
lead["lastname"] = entity.Attributes["new_lastname"];

if (entity.Attributes.Contains("new_firstname"))
lead["firstname"] = entity.Attributes["new_firstname"];

if (entity.Attributes.Contains("new_businessphone"))
lead["telephone1"] = entity.Attributes["new_businessphone"];

if (entity.Attributes.Contains("new_addressstreet1"))
lead.Attributes["address1_line1"] = entity["new_addressstreet1"];

if (entity.Attributes.Contains("new_city"))
lead.Attributes["address1_city"] = entity["new_city"];

if (entity.Attributes.Contains("new_stateprovince"))
lead.Attributes["address1_stateorprovince"] = entity["new_stateprovince"];

if (entity.Attributes.Contains("new_zippostalcode"))
lead.Attributes["address1_postalcode"] = entity["new_zippostalcode"];

Guid Lid=  service.Create(lead);


Copy all activities associated with an entity to another entity through Plugin in Dynamics CRM 2011

Copy all activities associated with entity to other entity thru Plugin in MS Dyanmcis

Requirement: Suppose you are copying over a record from an entity to another entity and you wanted to copy over the realted activities as well. Suppose you a custom Prospect entity record which have 2 task activites associated with, if you have to copy both tasks to another entity lets says Lead entity along with data.
Following is the Plugin you can use on Update Event.

if (entity.LogicalName == "new_prospect")
           {

  try
      {
         Entity lead = new Entity("lead");

         ColumnSet cols = new ColumnSet();
         cols.AddColumns(new string[] { "new_pipelinestatus", "new_rating", "new_lastname", "new_firstname", "new_businessphone", "new_addressstreet1", "new_city", "new_stateprovince", "new_zippostalcode", "new_updatecounter" });

entity = service.Retrieve("new_prospect", entity.Id, cols);

Guid Lid=  service.Create(lead);

 // copy activities
 var query = new QueryExpression("task");
query.ColumnSet = new ColumnSet(true);

//regardingobjectid this will get all activities of Prospect entity.
query.Criteria.AddCondition(new ConditionExpression("regardingobjectid", ConditionOperator.Equal, entity.Id));
                                           
                                                                                        

var activities = service.RetrieveMultiple(query).Entities;

foreach (var activity in activities)
{
  activity.Attributes.Remove("activityid");
  activity.Id = Guid.NewGuid();
  string regardingaccountype = "lead";
  activity["regardingobjectid"] = new EntityReference(regardingaccountype, Lid);

  service.Create(activity);

}

 

Random Number Generation through plug-in in MS Dynamics 2011

The Requirement is to generate a Unique Random Auto-generated Number while creating a record in Custom Prospect entity.

public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service =  (IOrganizationService)factory.CreateOrganizationService(context.UserId);

            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
            {
                Entity entity = (Entity)context.InputParameters["Target"];
                int count = 0;
                if (entity.LogicalName == "new_prospect")
                {
                    // A Prospect number attribute should not already exist because
                    // it is system generated.
                 

                    if (entity.Attributes.Contains("new_prospectnumber") == false)
                    {
                        // Create a new Prospect number attribute, set its value, and add
                        // the attribute to the entity's attribute collection.
                        Random rndgen = new Random();
                        entity.Attributes.Add("new_prospectnumber", rndgen.Next().ToString());
                        entity.Attributes.Add("new_updatecounter", count.ToString());
                       
                    }
                    else
                    {
                        // Throw an error, because Prospect numbers must be system generated.
                        // Throwing an InvalidPluginExecutionException will cause the error message
                        // to be displayed in a dialog of the Web application.
                        throw new InvalidPluginExecutionException("The Prospect number can only be set by the system.");
                    }
                }
            }
        }

Thursday, June 20, 2013

Code to keep the count of a Record has been modified


Hello All,

An interesting request came from customer to find a way that how many times a record has been updated after creation and if Plug-in can be avoided.

I just implemented the request with small JavaScript.
Here is the code that you have write on the load of the form:

updatecounter is the function that determines if the Form is Create Mode or Update mode and then set the value to a custom field in the form called "Counter".




























Javascript Function:

function updatecounter()
{
var FormType = Xrm.Page.ui.getFormType();
var count = Xrm.Page.getAttribute("Replace_with_Your_Field_Name").getValue();

if (FormType == 1)  // Checks if the form is in create mode

{

Xrm.Page.getAttribute("Replace_with_Your_Field_Name").setValue('0'); // Sets the value of the field to 0
Xrm.Page.getAttribute("Replace_with_Your_Field_Name").setSubmitMode("always"); // Force submit as field is read only.

}

if (FormType == 2 && Xrm.Page.data.entity.getIsDirty()) // Checks if the form is in update mode and if anything changed in the form.

{
    count = parseInt(count)+1;
    count = count.toString();
    Xrm.Page.getAttribute("Replace_with_Your_Field_Name").setValue(count);
    Xrm.Page.getAttribute("Replace_with_Your_Field_Name").setSubmitMode("always");
}
}

Save the customization and Publish.

This is pretty much it is.

Result :



















Thank You at looking at my post.




Power Automate Optimization: Filter Rows vs Trigger Conditions - When and Why to Use Each

Filter Rows vs Trigger Conditions in Power Automate Filter Rows vs Trigger Conditions in Power Automate Why your flow...