Plugin Development: Retrieve data using images

Images are useful for data comparison before and after core operation. We can register plugins on two type of images:

  • Pre-Image
  • Post-Image

Pre-Image can be used for retrieving the value of an entity attribute before core operation takes place.
Post-Image can be used for retrieving the value of an entity attribute after the core operation has taken place.

Scenario: On contact entity we have email address field. Let’s stop users from updating the email address field by showing them the old and new values.

using System;
using Microsoft.Xrm.Sdk;

namespace HelloPlugin
{
public class PreImagePlugin: IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

// Get a reference to the Organization service.
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);

if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];

try
{
//Implement Plugin Business Logic here
string newemailaddress = string.Empty;

if (entity.Attributes.Contains("emailaddress1"))
{
newemailaddress = entity.Attributes["emailaddress1"].ToString();
}

Entity preImageContact = (Entity)context.PreEntityImages["PreImage"]; //PreImage is user defined name you can name anything.

string oldemailaddr = preImageContact.Attributes["emailaddress1"].ToString(); //preImageContact will provide us the value which was saved before the update event.

throw new InvalidPluginExecutionException("The email address is modified from " + oldemailaddr + " to " + newemailaddress);
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException(ex.Message);
}
}
}
}
}

Below is the screenshot of the exception message thrown by our plugin:

Figure 1: Populating email address using pre-image

Plugin Development: Duplicate Check

Today we will learn how to restrict users from entering duplicate value in MS Dynamics CRM.

Let’s take as an example of Contact entity where we need to restrict users from entering duplicate email address which is already present in CRM while creating or updating a contact record.

I know there would a thought in your mind why don’t we use Duplicate Detection rule instead of plugin. So the answer to this question is duplicate detection rule will give user a warning message about the presence of duplicate record but still user will have the ability to ignore the warning message and save the record. Therefore, plugin is required for restricting users from entering duplicate records.

Note*: Below are the different techniques using which we can retrieve records. In this plugin we will be using Query Expression.

  • Fetch XML
  • Using Retrieve
  • Query Expression
  • Query By Attribute
  • LINQ
using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;

namespace HelloPlugin
{
public class DuplicateCheck: IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

// Get a reference to the Organization service.
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);

if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
//Obtain the target entity from the input parameter
Entity contact = (Entity)context.InputParameters["Target"];

try
{
//Implement Plugin Business Logic here
string email = string.Empty; //Variable declared to check whether emailaddress field is empty or not.

if (contact.Attributes.Contains("emailaddress1"))
{
email =  contact.Attributes["emailaddress1"].ToString();

QueryExpression query = new QueryExpression("contact");
query.ColumnSet = new ColumnSet(new string[] { "emailaddress1" });
query.Criteria.AddCondition("emailaddress1", ConditionOperator.Equal, email);

EntityCollection collection = service.RetrieveMultiple(query);

if (collection.Entities.Count > 0)  //Check if any record is present with duplicate email address
{
   throw new InvalidPluginExecutionException("Contact with email   already exist");
}
}
}
catch (Exception ex)
{
   throw new InvalidPluginExecutionException(ex.Message);
}
}
}
}
}

Points to Remember for registering the plugin. Add two steps one for create contact another for update contact.

  • Message = Create and Update
  • Primary Entity = contact
  • Pipeline Event = PreValidation

Hope this helps!!

Plugin Development: Create follow up task on create of Contact.

Create a follow up Task on create of Contact. The task should be completed in 2 days from the contact created on date.

Register the Plugin on:

  • Message = Create
  • Primary Entity = contact
  • Pipeline Event = PostOperation
using System;
using Microsoft.Xrm.Sdk;

namespace HelloPlugin
{ 
public class CreateTask: IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

// Get a reference to the Organization service.
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);

if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
//Obtain the target entity from the input parameter
Entity contact = (Entity)context.InputParameters["Target"];
try{
//Implement Plugin Business Logic inside try block
Entity taskRecord = new Entity("task");   //Creating object taskRecord of task entity.

//Single line of text(String fields)Append Follow Up on Task entity Subject field 
taskRecord.Attributes.Add("subject", "Follow Up"); 
//Append Need to follow up with contact statement on Task entity description field 
taskRecord.Attributes.Add("description", "Need to follow up with contact");   

//Set value in Date field
taskRecord.Attributes.Add("scheduledend", DateTime.Now.AddDays(2));  //Added 2 days from the Contact creation date.

//Set value in Optionset field (use Optionset value not lable) 
taskRecord.Attributes.Add("prioritycode", new OptionSetValue(2));  

//Set Parent Record to Task record.
//taskRecord.Attributes.Add("regardingobjectid", new EntityReference("contact", contact.Id)); //Old Methodology

taskRecord.Attributes.Add("regardingobjectid", contact.ToEntityReference());//New Methodology -- Link to Contact Record.

//Create a task record
Guid taskGuid = service.Create(taskRecord);
}

catch (Exception ex)
{
   throw new InvalidPluginExecutionException(ex.Message);
}
}
}
}
}
Figure 1: On create of Contact, follow up task got automatically created.