dynamically filter the CRM 2011 view via plugin

Unanswered dynamically filter the CRM 2011 view via plugin

  • Sunday, August 12, 2012 9:15 PM
     
      Has Code

    We need to restrict users to certain price-list and each pricelist has a lookup for business unit.  I need to filter the query using RetrieveMultiple Message whenever user search for the price-list either using "Advanced Find" or Lookup view or any view associated to PriceList. I found some code samples on the net and come up with below. However, I am not successful with this. Any help from experts is appreciated. 

       public void Execute(IServiceProvider serviceProvider)
          {
            // Obtain the execution context from the service provider.
             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);
    
             // Get a reference to the tracing service.
             ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
    
             //if (context.Mode == 0 && context.Stage == 10 && context.MessageName.Equals("RetrieveMultiple") )
            {
                 // The InputParameters collection contains all the data passed in the message request.
              
                Entity sysuser = new Entity("systemuser");
                sysuser = service.Retrieve("systemuser", context.InitiatingUserId, new ColumnSet("businessunitid"));
                _unitguid = sysuser.GetAttributeValue<EntityReference>("businessunitid").Id;
    
                 if (context.InputParameters.Contains("Query"))
                 {
                    if (context.InputParameters["Query"] is QueryExpression)
                       {
         
                        // Get the QueryExpression from the property bag
                       QueryExpression objQueryExpression = (QueryExpression)context.InputParameters["Query"];
    
                       if (objQueryExpression.EntityName == "savedquery" && objQueryExpression.Criteria != null && objQueryExpression.Criteria.Conditions != null)
                       {
                           ConditionExpression businessunitCondition = new ConditionExpression("new_businessunit", ConditionOperator.Equal, _unitguid);
                           objQueryExpression.Criteria.Conditions.Add(businessunitCondition);
                           context.InputParameters["Query"] = objQueryExpression;
                       }
                     }
    
                 }
             }
          }

    I registered at pre-event; RetrieveMultiple Message for PriceLevel Entity. 

    It doesn't work - when the user tried to select pricelist from advanced Find, he still sees all

    What am I missing here? Any help is appreciated. 


    • Edited by CRM elite Sunday, August 12, 2012 9:16 PM
    •  

All Replies

  • Monday, August 13, 2012 6:44 AM
     
     

    hi crm_elite,

    I think your code is fine. Why dont you try profiler and debug the error? And also add a line to check whether the entity is Price List orelse this plugin will do the same for all the entities.

  • Monday, August 13, 2012 11:34 AM
     
     
    does the profile work for CRM 2011 online? could you point me to some resources on that? 
  • Monday, August 13, 2012 12:47 PM
    Moderator
     
     

    One possible issue is that lookups and advanced finds would typically use a FetchExpression, rather than a QueryExpression, and your code is only acting if a QueryExpression is passed.

    To handle a FetchExpression, you could parse and manipulate the FetchXml, but this can get messy. Alternatively, you should be able to use a FetchXmlToQueryExpression request to convert it to a QueryExpression


    Microsoft CRM MVP - http://mscrmuk.blogspot.com  http://www.excitation.co.uk


  • Monday, August 13, 2012 12:51 PM
     
     

    hi,

    In plugin registration tools, there will be a tab called "Install Profiler", just click it after selecting your Step. Then there will be an option called "profile", click it. Then again Execute your plugin and Save the error details(note:now the Error details contents will be in diff format).Then come to your plugin and insert breakpoints and select Tools->Attach to process and select Plugin reg tool and select OK. After that, in plugin reg tool, click debug. Select the projectname.dll file and errordetails.txt appropriately and click Debug.

    Now find out actually what the problem is...

     

    if helpful,"vote as helpful" and mark as answer.

  • Monday, August 13, 2012 2:00 PM
     
      Has Code

    Thanks David. That's a good point.  I tried the code as below but still no luck. perhaps I am missing something. 

       public void Execute(IServiceProvider serviceProvider)
          {
            // Obtain the execution context from the service provider.
             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);
    
             // Get a reference to the tracing service.
             ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
             //throw new Exception("message name " );
           
             //if (context.InputParameters.Contains("Target") &&
             //    context.InputParameters["Target"] is Entity)
             //{
             //    Entity pricelist = (Entity)context.InputParameters["Target"];
             //    if (pricelist.LogicalName != "pricelevel")
             //    { return; }
             //}
    
             if (context.Mode == 0 && context.Stage == 10 && context.MessageName.Equals("RetrieveMultiple") )
            {
                 // The InputParameters collection contains all the data passed in the message request.
              
                Entity sysuser = new Entity("systemuser");
                sysuser = service.Retrieve("systemuser", context.UserId, new ColumnSet("businessunitid"));
                _unitguid = sysuser.GetAttributeValue<EntityReference>("businessunitid").Id;
    
    
                //if (context.InputParameters.Contains("FetchXml"))
                 {
                     //if (context.InputParameters["Query"] is FetchExpression || context.InputParameters["Query"] is QueryExpression )
                     if (context.InputParameters.Contains("FetchXml"))
                     {
         
                        // Get the QueryExpression from the property bag
                           //FetchExpression objFetch = (FetchExpression)context.InputParameters["Query"];
    
                           string FetchXml = (String)context.InputParameters["FetchXml"];
                           FetchXmlToQueryExpressionRequest req = new FetchXmlToQueryExpressionRequest();
                           req.FetchXml = FetchXml;
                           FetchXmlToQueryExpressionResponse resp = (FetchXmlToQueryExpressionResponse)service.Execute(req);
    
    
                           QueryExpression objQueryExpression = resp.Query;//  (QueryExpression)context.InputParameters["Query"];
    
                       ConditionExpression businessunitCondition = new ConditionExpression("new_businessunit", ConditionOperator.Equal, _unitguid);
                       objQueryExpression.Criteria.Conditions.Add(businessunitCondition);
                       
                       FilterExpression newFilter = new FilterExpression()
                       {
                           FilterOperator = LogicalOperator.Or,
                           Conditions = { businessunitCondition }
                       };
    
                       objQueryExpression.Criteria.AddFilter(newFilter);
                     
                     }
    
                 }
             }
          }

  • Monday, August 13, 2012 2:01 PM
     
     
    naveen, i register the plugin on the pricelevel entity. still do I need to check the entity in my code. 
  • Monday, August 13, 2012 2:28 PM
     
     
    Hi, i tried to install the profiler per your steps. I clicked ont eh Profile and it says "stop profiling" indicating that it is started. I went to CRM online and pulled the view. it din't give me any error details.  I came to my visual studio and put a breakpoint but I don't see any Process to attach in the VS tools menu? 
  • Monday, August 13, 2012 4:24 PM
     
     

    Ok. I registered the plug-in in "savedquery" entity on RetrieveMultiple Message. I am checking the entity inside the code for pricelist and then add the condition.  However, I am getting error message 

    'SavedQuery' entity doesn't contain attribute with Name = 'new_businessunit' !

    It looks like I can't filter by custom fields! Is it? 
    • Edited by CRM elite Monday, August 13, 2012 4:25 PM
    •  
  • Monday, August 13, 2012 7:51 PM
    Moderator
     
     
    The plugin should be registered on the pricelevel entity, not savedquery

    Microsoft CRM MVP - http://mscrmuk.blogspot.com/ http://www.excitation.co.uk

  • Tuesday, August 14, 2012 5:10 AM
     
     

    HI CRM elite,

    I would try registering the plugin on the Execute message as the queries are performed with a FetchXML which is processed by the Execute message, don’t spend time with the plugin profiler on RetriveMultiple message as it won’t work, it basically works for updates or create messages.


    Regards,
    Damian Sinay

  • Tuesday, August 14, 2012 3:16 PM
     
     

    Hi.

    There are two events where you will need to implement the logic (mode=synchronous, stage=pre operation):

    • RetrieveMultiple event for the required entity / entities

    Here you will need to build your dynamic QueryExpression and replace it to 'Query' in the InputParameters in the plugin. (you should remove the conditions in QueryExpression to check the entity name, as you want to apply the filter in multiple places.

    • Execute

    For this part, "execute" contains 'FetchXml' as InputParameter. What you will need to do is to replace the FetchXml with your dynamic build.

    A further note, as this type of plugin is always heavy on server load

    1. Limit the data retrieved. fields not used should be be included
    2. Limit the entities it will run in ealy steps. (such as 'return' if the entity is not the target entity or entities)
    3. Make sure exception handling are effective but not overdone.

    Jaimie


    • Edited by Jaimie_J Tuesday, August 14, 2012 3:17 PM
    •