How to transfer notes from a Lead as it's converted
Category: Extending MS CRM | Posted on Monday, May 12, 2008

As a Lead is converted into a Contact, Account or an Opportunity all notes made on that Lead are not copied or transferred to the newly created Contact, Account or Opportunity. To some companies this is acceptable or it’s what they want but to others this is a problem. This "problem" exists on both MS CRM 3.0 and 4.0.

Below you will find the source code for a MS CRM 4.0 plug-in that will transfer any notes made on a Lead onto the Contact, Account or Opportunity that this Lead is converted into. You can make a similar solution on MS CRM 3.0 using Callouts. I haven’t got much experience making callouts and so I only provide a solution for MS CRM 4.0.

For this to work you need to register the plug-in to the post create stage of the Contact, Account and Opportunity create event using the plug-in registration tool that is included in the MS CRM 4.0 SDK. I prefer using synchronous as execution mode but asynchronous will also work.

Remember you need to make reference to Microsoft.Crm.Sdk and Microsoft.Crm.SdkTypeProxy in your Solution and also to sign it.

Source code
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Sdk.Query;

namespace DollerupIT.TransferNotes
public class CreateNotesOnNewEntity: IPlugin

// The execute method that will run as the create Contact, Account and Opportunity event happens.
public void Execute(IPluginExecutionContext context) {

// Make sure the input parameters contains a property named Target and that that property is of type DynamicEntity.
if(context.InputParameters.Properties.Contains("Target") &&
context.InputParameters.Properties["Target"] is DynamicEntity) {

ICrmService service = context.CreateCrmService(true);

// Create a DynamicEntity from the input parameters.
DynamicEntity Inputentity;
Inputentity = (DynamicEntity)context.InputParameters.Properties["Target"];

if (context.PrimaryEntityName == "contact" || context.PrimaryEntityName == "account" || context.PrimaryEntityName == "opportunity" ){

// Make sure that the Lead id is among the properties before continuing.
if (!Inputentity.Properties.Contains("originatingleadid")) { return; }

// Assign the Lead id and the id of the newly created Contact, Account or Opportunity to local variables for later use.
Guid originatingleadid = ((Lookup)Inputentity.Properties["originatingleadid"]).Value;
Guid newEntityid = (Guid)context.OutputParameters.Properties["id"];

// Create the conditions for the query that is to collect all the notes related to the Lead.
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "objectid";
condition.Operator = ConditionOperator.Equal;
condition.Values = new Object[] { originatingleadid };
// Create the fiter for the query that is to collect all the notes related to the Lead.
FilterExpression filter = new FilterExpression();
filter.FilterOperator = LogicalOperator.And;

// Create the query object.
QueryExpression query = new QueryExpression();
query.ColumnSet = new AllColumns();
query.EntityName = EntityName.annotation.ToString();
query.Criteria = filter;

// Retrieve all the notes related to the Lead as and BusinessEntityCollection.
BusinessEntityCollection retrived = service.RetrieveMultiple(query);

// Loop through all the notes and update them so that they are now related to the newly created Contact, Account or Opportunity.
foreach (object retrivedObject in retrived.BusinessEntities)
annotation note = (annotation)retrivedObject;

EntityNameReference newReference = new EntityNameReference();
newReference.Value = context.PrimaryEntityName;

note.objecttypecode = newReference;
note.objectid.Value = newEntityid;

All source code on this website is provided as is. If you use any of my solutions or just parts of them I’m not to be held responsible for any errors or loss of data you might encounter.