Plug-ins vs. Workflows in Microsoft Dynamics CRM


 
 Both workflows and plug-ins can attach to exactly the same events. Well, plug-ins have available a couple of more events but essentially both work on top of the same event model.Remember also that workflows always run asynchronous and hence, the Asynchronous Processing Service must be running on the server in order to run.

Workflows are more suitable if:

  • you want to achieve simple tasks faster, such as sending an e-mail or creating / updating assigning records. These actions can be set up very quickly with a workflow without any need of writing code.
  • you want to easily scale things to managers (if they were setup for user records), as it is possible to assign records to them.
  • you want to allow an advanced user to make changes to logic. As using the integrated workflow designer is user-friendly, an advanced user would be able to edit an existing workflow and change some rules according to business changes.
  • the logic should be available to be run on demand. I mean, when you are within an entity and navigates to “workflows” option in the left pane, all workflows marked as available to run on demand can be executed making them independent of an event trigger.
  • you want to send emails making use of templates and attaching files.

Workflows also allow running child workflows which may make a lot of sense in some scenarios. Nevertheless, be careful if you need the child workflow results in order to make decisions on your main workflow, as child workflows always run asynchronous, which means that it will trigger the child workflow and continue. If you need your primary workflow to wait until child ends, you will need to write a custom activity.

On the other hand, plug-ins are more suitable if:

  • you need to manipulate data before is saved.
  • you need to make validations before submitting the operation.
  • you want to be able to cancel an operation based on your validations.
  • immediate response to the user is needed.
  • you need retrieve values and/or take actions after operation has been completed (i.e. getting and autogenerated id)

It is important to note that since Dynamics CRM 4, plug-ins can also be configured to run asynchronous (Mode attribute while registering plug-in). Nevertheless, pre-event asynchronous plug-ins are not supported. In this case, you will have to set it up as synchronous mode.

Another important thing about plug-ins is the Deployment option which says if the plug-in is going to be executed on the server and/or Outlook client. If both executions are set up and client goes offline and online, plug-in calls are triggered after synchronization so be prepared in this case to execute your code twice!

Regarding to security:

  • Workflows triggered automatically will run under the security context of the workflow owner. On the contrary, if executed on demand, the security context of the user who executed the workflow will be used.
  • Plug-ins execute under the security context of the CRM Web application pool identity (typically NETWORK SERVICE). As this account typically maps to generic CRM SYSTEM user this typically works fine.

However, within plug-ins you can make use of impersonation to work under the credentials of the user who is making the request. For doing so, you just need to pass True to the CreatCrmService method under the context object.If you need to always impersonate with a specific user, you can do that by passing True as above and setting impersonatinguserid attribute while registering the plug-in.It is important to know that plug-in impersonation does not work offline. The logged on user credentials are always used in this case.

Some other important url for reference are..
http://msdn.microsoft.com/en-us/library/dd393303.aspx
http://blogs.msdn.com/lezamax/archive/2008/04/02/plug-in-or-workflow.aspx.
Hope it helps..

Mail Merge Using Microsoft Dynamics CRM 4.0 and Microsoft Office Word


How to do a mail merge from Microsoft Outlook, using Dynamics CRM data and Microsoft Office Word. Outlook and Word version 2007 shown in this video

via Mail Merge Using Microsoft Dynamics CRM 4.0 and Microsoft Office Word.

Update Rollup 13 for Microsoft Dynamics CRM 4.0


Update Rollup 13 for Microsoft Dynamics CRM 4.0

http://blogs.msdn.com/b/crm/archive/2010/09/23/update-rollup-13-for-microsoft-dynamics-crm-4-0.aspx

What’s new in Microsoft Dynamics CRM 2011?


1.) New application features

  • Visualization. On demand graphical charts for many record types.
  • Improved user interface that includes the Office Ribbon design and more streamlined forms.
  • Connections. A new feature for establishing relationships between records.
  • Recurring activities. Schedule activities, such as appointments, that repeat.
  • Queue enhancements.
  • Auditing. To enable record level auditing, go to System Settings under Settings, click the Auditing tab, and then click Enable.
  • Field level security. Manage user and team permissions to read, create, or write information in secured fields.
  • Solutions. Solutions are packages of software that you can install or remove from your Microsoft Dynamics CRM organization.


2.) Sandbox Processing Service

The Sandbox Processing Service server role enables an isolated environment to allow for the execution of custom code, such as plug-ins. This isolation reduces the possibility of custom code affecting the operation of the organizations in the Microsoft Dynamics CRM deployment.


3.) Claims-based authentication support

Using federation identity technology such as AD FS 2.0 (formerly known as “Geneva”), Microsoft Dynamics CRM supports claims-based authentication. This technology helps simplify access to applications and other systems by using an open and interoperable claims-based model that provides simplified user access and single sign-on to applications on-premises, cloud-based, and even across organizations. For more information about the claims-based authentication model, see Identity and Access Management.


4.) Add or remove a server role

You can now install individual server roles by using the Microsoft Dynamics CRM Server Setup Wizard. Similarly, you can add a server role, or change or remove installed server roles from Programs and Features in Control Panel.


5.)    SharePoint documentation management

SharePoint documentation management lets you view Microsoft Dynamics CRM data in Microsoft SharePoint. This is an optional feature that you can configure in the Settings area of the Microsoft Dynamics CRM Web application.

For More details, Please download CRM 2011 Implementation Guide from below link.

http://www.microsoft.com/downloads/en/details.aspx?FamilyID=0c7dcc45-9d41-4e2e-8126-895517b4274c&displayLang=en#SystemRequirements

Troubleshooting Microsoft CRM Asynchronous process jobs


1.       If any of the job’s status has changed from “Publishing” to “Unpublished”, most likely there are exceptions that caused the job to fail.

a.       Run the SQL script to understand the cause

USE Microsoft_MSCRM

GO

SELECT Name, ErrorCode, Message, *

FROM AsyncOperation

WHERE OperationType = 7

ORDER BY CompletedOn DESC

Message column should contain more descriptive message than what is displayed in the MS CRM UI.  If this still is unclear then

b.      Enable MS CRM Tracing by following instructions from the support link

http://support.microsoft.com/kb/907490

Create three registry keys

TraceEnabled = 1

TraceDirectory = <CRM InstallPath>\CRMTrace

TraceRefresh = 0

2.       Understanding how many records still needs to be processed per Duplicate Detection Rule

a.       MS CRM generates tables with random names to store match code.

USE Microsoft_MSCRM

GO

SELECT Name, MatchingEntityMatchCodeTable, *

FROM DuplicateRule

n  Example

SELECT COUNT(*)

FROM account

WHERE accountId NOT IN (SELECT ObjectId FROM <MatchingEntityMatchCodeTable from Duplicate Rule table>)

Similarly we can troubleshoot Microsoft CRM Workflows and other Asynchronous Jobs

Below are the list of Asynchronous Job types and there values

The AsyncOperationType class exposes the following members.

Field Value Description
ActivityPropagation 6
BulkDelete 13
BulkDeleteChild 23
BulkDetectDuplicates 8
BulkEmail 2
CalculateOrgMaxStorageSize 22
CalculateOrgStorageSize 18
CleanupInactiveWorkflowAssemblies 32
CollectOrgDBStats 19
CollectOrgSizeStats 20
CollectOrgStats 16
CollectSqmData 9
DatabaseLogBackup 26
DatabaseTuning 21
DeletionService 14
Event 1
FullTextCatalogIndex 25
Import 5
ImportingFile 17
IndexManagement 15
Parse 3
PersistMatchCode 12
PublishDuplicateRule 7
QuickCampaign 11
ReindexAll 30
ShrinkDatabase 28
ShrinkLogFile 29
StorageLimitNotification 31
Transform 4
UpdateContractStates 27
UpdateStatisticIntervals 24
Workflow 10

Delete log and rebuild index of AsyncOperationBase and WorkflowLogBase table in Dynamics CRM using SQL Job


USE [msdb]
GO
/****** Object:  Job [Async-CleanUP]    Script Date: 05/27/2010 12:36:09 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [[Uncategorized (Local)]]]    Script Date: 05/27/2010 12:36:09 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]’ AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N’JOB’, @type=N’LOCAL’, @name=N'[Uncategorized (Local)]’
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N’Async-CleanUP’,
@enabled=1,
@notify_level_eventlog=0,
@notify_level_email=0,
@notify_level_netsend=0,
@notify_level_page=0,
@delete_level=0,
@description=N’No description available.’,
@category_name=N'[Uncategorized (Local)]’,
@owner_login_name=N’domain\username’, @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [Async-CleanUp-TSQL]    Script Date: 05/27/2010 12:36:09 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N’Async-CleanUp-TSQL’,
@step_id=1,
@cmdexec_success_code=0,
@on_success_action=1,
@on_success_step_id=0,
@on_fail_action=2,
@on_fail_step_id=0,
@retry_attempts=0,
@retry_interval=0,
@os_run_priority=0, @subsystem=N’TSQL’,
@command=N’IF EXISTS (SELECT name from sys.indexes
WHERE name = N”CRM_AsyncOperation_CleanupCompleted”)
DROP Index AsyncOperationBase.CRM_AsyncOperation_CleanupCompleted
GO
CREATE NONCLUSTERED INDEX CRM_AsyncOperation_CleanupCompleted
ON [dbo].[AsyncOperationBase] ([StatusCode],[StateCode],[OperationType])
GO
declare @DeleteRowCount int
Select @DeleteRowCount = 2000
declare @DeletedAsyncRowsTable table (AsyncOperationId uniqueidentifier not null primary key)
declare @continue int, @rowCount int
select @continue = 1
while (@continue = 1)
begin
begin tran
insert into @DeletedAsyncRowsTable(AsyncOperationId)
Select top (@DeleteRowCount) AsyncOperationId
from AsyncOperationBase
where OperationType in (1, 9, 12, 25, 27, 10) AND StateCode = 3 AND StatusCode in (30, 32)

Select @rowCount = 0
Select @rowCount = count(*) from @DeletedAsyncRowsTable
select @continue = case when @rowCount <= 0 then 0 else 1 end

if (@continue = 1)
begin
delete WorkflowLogBase from WorkflowLogBase W, @DeletedAsyncRowsTable d
where W.AsyncOperationId = d.AsyncOperationId

delete BulkDeleteFailureBase From BulkDeleteFailureBase B, @DeletedAsyncRowsTable d
where B.AsyncOperationId = d.AsyncOperationId

delete AsyncOperationBase From AsyncOperationBase A, @DeletedAsyncRowsTable d
where A.AsyncOperationId = d.AsyncOperationId

delete @DeletedAsyncRowsTable
end

commit
end
–Drop the Index on AsyncOperationBase
DROP INDEX AsyncOperationBase.CRM_AsyncOperation_CleanupCompleted

–rebuild index
— Rebuild Indexes & Update Statistics on AsyncOperationBase Table
ALTER INDEX ALL ON AsyncOperationBase REBUILD WITH (FILLFACTOR = 80, ONLINE = OFF,SORT_IN_TEMPDB = ON, STATISTICS_NORECOMPUTE = OFF)
GO
— Rebuild Indexes & Update Statistics on WorkflowLogBase Table
ALTER INDEX ALL ON WorkflowLogBase REBUILD WITH (FILLFACTOR = 80, ONLINE = OFF,SORT_IN_TEMPDB = ON, STATISTICS_NORECOMPUTE = OFF)
GO
‘,
@database_name=N'<Organization Name>_MSCRM’,
@flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N’Async-Cleanup-Schedule’,
@enabled=1,
@freq_type=8,
@freq_interval=18,
@freq_subday_type=1,
@freq_subday_interval=0,
@freq_relative_interval=0,
@freq_recurrence_factor=1,
@active_start_date=20091116,
@active_end_date=99991231,
@active_start_time=0,
@active_end_time=235959
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)’
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:

Update database statistics everyday


USE [msdb]
GO
/****** Object:  Job [Data_Update_statistics_everyday]    Script Date: 05/27/2010 12:32:03 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [Database Maintenance]    Script Date: 05/27/2010 12:32:03 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N’Database Maintenance’ AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N’JOB’, @type=N’LOCAL’, @name=N’Database Maintenance’
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N’Data_Update_statistics_everyday’,
@enabled=1,
@notify_level_eventlog=0,
@notify_level_email=0,
@notify_level_netsend=0,
@notify_level_page=0,
@delete_level=0,
@description=N’Data_Update_statistics_everyday’,
@category_name=N’Database Maintenance’,
@owner_login_name=N’domain\username’, @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [Data_Update_statistics_everyday]    Script Date: 05/27/2010 12:32:03 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N’Data_Update_statistics_everyday’,
@step_id=1,
@cmdexec_success_code=0,
@on_success_action=1,
@on_success_step_id=0,
@on_fail_action=2,
@on_fail_step_id=0,
@retry_attempts=0,
@retry_interval=0,
@os_run_priority=0, @subsystem=N’TSQL’,
@command=N’EXEC Sp_msforeachtable ”Update Statistics ? ”
‘,
@database_name=N'<Organization Name>_MSCRM’,
@flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N’update_stats_12_AM’,
@enabled=1,
@freq_type=4,
@freq_interval=1,
@freq_subday_type=1,
@freq_subday_interval=0,
@freq_relative_interval=0,
@freq_recurrence_factor=0,
@active_start_date=20100412,
@active_end_date=99991231,
@active_start_time=40000,
@active_end_time=235959
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)’
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:

Rebuild Index of a database table


DECLARE @Database VARCHAR(255)
DECLARE @Table VARCHAR(255)
DECLARE @cmd NVARCHAR(500)

DECLARE @fillfactor INT
SET @fillfactor = 90

CREATE Table #databaseName (dbid int identity(1,1), DbName Varchar(255))

Insert into #databaseName
SELECT name
FROM   MASTER.dbo.sysdatabases
—  WHERE  name NOT IN ( ‘master’, ‘model’, ‘msdb’, ‘tempdb’, ‘distrbution’ )
WHERE  name IN ( ‘OD’)
ORDER  BY 1

CREATE Table #TableName (Tableid int identity(1,1), TableName Varchar(1000))

declare @DbCnt int
declare @TblCnt int
declare @i int
declare @j int

select @i = 1
select @j = 1

select @DbCnt = Max(dbid) from #databaseName

WHILE @i <= @Dbcnt
BEGIN
SELECT @cmd = ‘Insert Into #TableName SELECT table_catalog + ”.” + table_schema + ”.” + table_name as tableName
FROM ‘ + DbName + ‘.INFORMATION_SCHEMA.TABLES WHERE table_type = ”BASE TABLE”’
from #databaseName where dbid = @i

— create table cursor
Print @cmd
EXEC (@cmd)

select @tblCnt = Max(Tableid) from #tableName

WHILE @j <= @tblcnt
BEGIN
— SQL 2000 command
–DBCC DBREINDEX(@Table,’ ‘,@fillfactor)
— SQL 2005 command
SELECT @cmd = ‘ALTER INDEX ALL ON ‘ + TableName + ‘ REBUILD WITH (FILLFACTOR = ‘ + Convert(VARCHAR(3), @fillfactor) + ‘)’
From #tableName where Tableid = @j

print @cmd
EXEC (@cmd)

Set @j =@j + 1
END

Set @i =@i + 1

END

drop table #databaseName
drop table #tableName

Populate lookup value on selection of another lookup


I had client requirement that on the selection of City (lookup), Region and Sub Region should be populated automatically which is read only field. To achieve this we mapped the city with region (lookup) and sub region (lookup) on the city entity. After writing below code I was getting following error.

There was an error with this field’s customized event.

Field:new_cityid

Event:onchange

Error:’ new_subregionid.value ‘ is null or not an object

I solved the issue with help of this link and answer posted by Adi Katz .

“The keyValues are only available when you use the lookup dialog. The form assistant does not contain the columns that are retrieved by the lookup and this is why the items array is empty.”

For details please visit below link.

http://social.microsoft.com/Forums/en-US/crmdevelopment/thread/ad9b5b22-da6b-4f20-9fd4-b7e46d9a7556

After this solution I added Sub Region field to lookup dialog (lookup view) and this solve my issue.

Put below code on OnChange of City Lookup field.

/*****Auto Populate SubRegion on Selection of City field******************/

if (crmForm.all.new_cityid.DataValue==null)

{
crmForm.all.new_subregionid.DataValue = null;
}

else

{

var lookup_guid;

var lookup_name;

var lookup_type;

var lookup_typename;

var lookupItem = new Array;

lookupItem = crmForm.all.new_cityid.DataValue;

lookup_guid=lookupItem[0].id;

lookup_name=lookupItem[0].name;

lookup_type=lookupItem[0].type;

lookup_typename=lookupItem[0].typename;

var subRegionName;

if(crmForm.all.new_cityid.items != null)

{
var lookupValues = crmForm.all.new_cityid.items[0].keyValues;
subRegionName = lookupValues.new_subregionid.value? lookupValues.new_subregionid.value : null;

}
else
{
subRegionName = null;

}

var subregionidvalue = GetAttributeValueFromID(lookup_typename, lookup_guid, ‘new_subregionid’);

if(subregionidvalue != null)

{
var subregionlookupData = new Array();

//Create an Object add to the array.

var subregionlookupItem = new Object();

//Set the id, typename, and name properties to the object.

subregionlookupItem.id = subregionidvalue;

regionlookupItem.typename = ‘new_subregion’;

regionlookupItem.name = subRegionName ;

// Add the object to the array.

subregionlookupData[0] = subregionlookupItem;

// Set the value of the lookup field to the value of the array.

crmForm.all.new_subregionid.DataValue = subregionlookupData;

crmForm.all.new_subregionid.ForceSubmit = true;

}

function GetAttributeValueFromID(sEntityName, sGUID, sAttributeName)

{

var sXml = “”;

var oXmlHttp = new ActiveXObject(“Msxml2.XMLHTTP.6.0”);

var serverurl = “”;

//set up the SOAP message

sXml += “<?xml version=\”1.0\” encoding=\”utf-8\” ?>”;

sXml += “<soap:Envelope xmlns:soap=\”http://schemas.xmlsoap.org/soap/envelope/\””;

sXml += ” xmlns:xsi=\”http://www.w3.org/2001/XMLSchema-instance\””;

sXml += ” xmlns:xsd=\”http://www.w3.org/2001/XMLSchema\”>”;

sXml += “<soap:Body>”;

sXml += “<entityName xmlns=\”http://schemas.microsoft.com/crm/2006/WebServices\”>” + sEntityName +

“</entityName>”;

sXml += “<id xmlns=\”http://schemas.microsoft.com/crm/2006/WebServices\”>” + sGUID + “</id>”;

sXml += “<columnSet xmlns=\”http://schemas.microsoft.com/crm/2006/WebServices\””;

sXml += ” xmlns:q=\”http://schemas.microsoft.com/crm/2006/Query\””;

sXml += ” xsi:type=\”q:ColumnSet\”><q:Attributes><q:Attribute>” + sAttributeName +

“</q:Attribute></q:Attributes></columnSet>”;

sXml += “</soap:Body>”;

sXml += “</soap:Envelope>”;

// send the message to the CRM Web service

oXmlHttp.open(“POST”, serverurl + “/MsCrmServices/2006/CrmService.asmx”,false);

oXmlHttp.setRequestHeader(“SOAPAction”,”http://schemas.microsoft.com/crm/2006/WebServices/Retrieve&#8221;);

oXmlHttp.setRequestHeader(“Content-Type”, “text/xml;charset=utf-8”);

oXmlHttp.setRequestHeader(“Content-Length”, sXml.length);

oXmlHttp.send(sXml);

// retrieve response and find attribute value

// retrieve the given attribute name in any XML namespace

var result = oXmlHttp.responseXML.selectSingleNode(“//*[local-name()=\”” +  sAttributeName +”\”]”);

if (result == null)

{

return “”;

}

else

{

return result.text;

}

}

}

Filtering multiple custom CRM Lookup


Let me explain the scenario..

We have a Model lookup and a variant Lookup on Lead form. Every variant is associated with a particular model. i.e One model have multiple Variant.

Eg.
Model          Varient
Alto             Alto LX
Alto             Alto Xcite
Alto             Alto LXI
SX4               SX4 VXI
SX4               SX4 ZXI Leather
SX4               SX4 ZXI
—————————-

Now Requirement is that when user select a model from Model lookup then only variant corresponding to selected model should be displayed to user when user click on variant lookup and disable the search in Variant lookup.

Write below code on Model OnChange event.

if(crmForm.all.new_modelid.DataValue != null )
{
var modelLookup=crmForm.all.new_modelid.DataValue;
var modelID=modelLookup[0].id;
var modelName=modelLookup[0].name;
var field=crmForm.all.new_variantid;

// Pass fetch xml through search value parameter
field.lookupbrowse = 1;
field.AddParam(“search”,”<fetch mapping=’logical’ distinct=’false’>”
+”<entity name=’new_varientmaster’>”
+”<attribute name=’new_varientmasterid’/>”
+”<attribute name=’new_name’/><attribute name=’createdon’/>”
+”<order attribute=’new_name’ descending=’false’/><filter type=’and’>”
+”<condition attribute=’new_modelnameid’ operator=’eq’ uiname='”+ modelName
+”‘ uitype=’new_modelmaster’ ”
+”value='”+ modelID +”‘ />”
+”</filter></entity></fetch>”

);
}

Note: Put below code if not already exist

The following code needs to be inserted anywhere in the <CRM site folder>\_controls\lookup\lookupsingle.aspx file if not already exist (if you have already code for filtering lookup)..

<script runat=”server”>
protected override void OnLoad( EventArgs e )
{
base.OnLoad(e);
crmGrid.PreRender += new EventHandler( crmgrid_PreRender );
}

void crmgrid_PreRender( object sender , EventArgs e )
{
// As we don’t want to break any other lookups, ensure that we use workaround only if
// search parameter set to fetch xml.
if (crmGrid.Parameters[“search”] != null && crmGrid.Parameters[“search”].StartsWith(“<fetch”))
{
crmGrid.Parameters.Add(“fetchxml”, crmGrid.Parameters[“search”]);

// searchvalue needs to be removed as it’s typically set to a wildcard ‘*’
crmGrid.Parameters.Remove(“searchvalue”);

// and then select it.
this._showNewButton = false;
}
}

</script>

For details  about lookupsingle.aspx code visit below link.

http://crm.georged.id.au/post/2008/02/16/Filtering-lookup-data-in-CRM-4.aspx

For Reference: Model is custom entity (new_modelmaster) which contains name attribute (i.e Model Name) and Variant is custom entity (new_variantmaster) which contain name attribute( variant Name ) and Model lookup(new_modelnameid) to map model with variant.

For building FetchXml Query find below link.

https://arvindcsit.wordpress.com/2010/09/08/using-the-advanced-find-for-fetchxml-builder/

Enjoy J