You are currently browsing the category archive for the ‘Plug-In’ category.

You can display dialog in MS CRM application from a plug-in. The code below is an example of a plug-in this.

using System;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;

namespace MyPlugins
   public class HelloWorldPlugin: IPlugin
      public void Execute(IPluginExecutionContext context)
         // Call the Microsoft Dynamics CRM Web services here or perform
         // some other useful work.
         throw new InvalidPluginExecutionException("Hello world!");

You can read more about this at the URL below.


I was recently looking to build a plug-in that got triggered when two account records were merged.

The plug-in needed to read properties from both the Master record and the sub-ordinate record and to do that I needed the ID of both records.
I couldn’t find much help in the SDK or on the web.

I’ve decided to post some of the code from my plug-in on my blog, just to help anyone who is trying to build something similar.

Good luck!

using System;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using System.Web;

namespace Merge_Plugin
	public class Plug_Merge : IPlugin
		public void Execute(IPluginExecutionContext context)
			Microsoft.Crm.Sdk.Moniker MasterRecord = null;
			Guid SubOrdinateRecord = new Guid();

			// Check whether the input parameters property bag contains a target.
			if (context.InputParameters.Properties.Contains("Target") &&
			   context.InputParameters.Properties["Target"] is Microsoft.Crm.Sdk.Moniker)
				// Obtain the target Moniker from the input parmameters.
				MasterRecord = (Microsoft.Crm.Sdk.Moniker)context.InputParameters.Properties["Target"];
			{ return;}

				//Get the ID of the MasterRecord
				string masterId = MasterRecord.Id.ToString();
				if (context.InputParameters.Properties.Contains("SubOrdinateId"))
					SubOrdinateRecord = (Guid)context.InputParameters.Properties["SubOrdinateId"];
					//Get the ID of the Sub Ordinate Record.
					string subId = SubOrdinateRecord.ToString();
			catch (Exception ex)
				throw new InvalidPluginExecutionException(
					  "An error occurred in the AccountMerge plug-in.", ex);

For asynchronous registered plug-ins (or workflow assemblies) you need to attach to the CrmAsyncService.exe process unlike the synchronous assemblies which can be debugged be attaching to the w3wp.exe.

The URL below will help.

So what is the difference between Plug-in disk deployment vs database deployment besides the obvious.

Well disk deployment is pretty similar to the callout deployment in MS CRM 3.0. The database deployment is the new leap forward. One big benefit of database deployment is that it enables automatic distribution of the plug-in to multiple Microsoft Dynamics CRM servers in a data center. Some thing thing that is not that simple with disk deployment.

A big benefit of disk deployment is that you are able to debug your plug-in, step through your code.

The sample code below shows how you can search for a contact based on the contacts firstname, lastname and company name.
You’ll need to link the contact and company entity.

// Create a column set holding the names of the columns to be retrieved.
ColumnSet cols = new ColumnSet();
cols.Attributes = new string[] { "contactid", "fullname" };</code>

// Create the ConditionExpression.
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "name";
condition.Operator = ConditionOperator.Like;
condition.Values = new string[] { Company + "%" };

// Build the filter based on the condition.
FilterExpression filter = new FilterExpression();
filter.FilterOperator = LogicalOperator.And;
filter.Conditions = new ConditionExpression[] { condition };

LinkEntity link = new LinkEntity();

// Set the LinkEntity properties.
link.LinkCriteria = filter;
link.LinkFromEntityName =;
link.LinkFromAttributeName = "parentcustomerid";
link.LinkToAttributeName = "accountid";
link.LinkToEntityName = EntityName.account.ToString();

ConditionExpression conditionFN = new ConditionExpression();
conditionFN.AttributeName = "firstname";
conditionFN.Operator = ConditionOperator.Like;
conditionFN.Values = new string[] { Firstname + "%" };

ConditionExpression conditionLN = new ConditionExpression();
conditionLN.AttributeName = "lastname";
conditionLN.Operator = ConditionOperator.Like;
conditionLN.Values = new string[] { Lastname + "%" };

FilterExpression cfilter = new FilterExpression();
cfilter.FilterOperator = LogicalOperator.And;
cfilter.Conditions = new ConditionExpression[] { conditionFN, conditionLN };

// Create an instance of the query expression class.
QueryExpression query = new QueryExpression();
query.EntityName =;
query.ColumnSet = cols;
query.Criteria = cfilter;
query.LinkEntities = new LinkEntity[] { link };

// Create the request.
RetrieveMultipleRequest retrieve = new RetrieveMultipleRequest();

// Set the request properties.
retrieve.Query = query;

// Execute the request.
RetrieveMultipleResponse retrieved2 = (RetrieveMultipleResponse)service.Execute(retrieve);

The sample code below demonstrates how to share a contact record with a user. This is very helpful if you want to allow multiple users to own a record.
My solution to the problem was to share the record with users when the “Secondary Owner” was set on the form.

        SecurityPrincipal principal = new SecurityPrincipal();
        principal.Type = SecurityPrincipalType.User;
        principal.PrincipalId = new Guid(userid.ToString());

        // Create the PrincipalAccess Object
        PrincipalAccess principalAccess = new PrincipalAccess();
        principalAccess.Principal = principal;
        // Gives the principal access to read
        principalAccess.AccessMask = AccessRights.ReadAccess | AccessRights.AppendAccess | AccessRights.AppendToAccess | AccessRights.WriteAccess;

        // Create the Target Object for the Request
        TargetOwnedContact target = new TargetOwnedContact();
        target.EntityId = new Guid(recordID.ToString());

        // Create the Request Object</span>
        GrantAccessRequest grant = new GrantAccessRequest();
        grant.PrincipalAccess = principalAccess;
        grant.Target = target;

        // Execute the Request
        GrantAccessResponse granted = (GrantAccessResponse)service.Execute(grant);