Call plugin from Javascript in Microsoft Dynamics CRM.

Wanted to share with you all a very interesting way to call plugins from you client side code in Microsoft Dynamics CRM to perform complex operations.Recently in our project  we had a requirement to determine duplicates for an entity based on some very complex business rules with integration from external system. Surely we can call the write some code in a plugin and register it in the pre-validation of Create/ update message of the entity. However our requirement was bit more complex. Not only we had to inform the user of the duplicates but also shown the user, the list of all the duplicates in a webresource popup from where the user can select one of the duplicates. And on top of that all this should be synchronous.

 

So. What can we do? Can’t we leverage the power of server side plugins to write some complex business logic. yes we can. Following is the approach we took.

 

  • 1. We created a entity in CRM which would act as the dummy entity in our purpose. We created a field called ‘new_data’ with type of string which would store the data that we need to pass to server side to process the logic of duplicate detection.
  • Next we create a fetchxml for this dummy entity. Lets say we need to pass account name to the server side to determine the duplicate. So we created a fetchxml in the below format where we are passing the value of account name as a condition for the new_data field.

var fetchString = ‘<fetch version=”1.0″ output-format=”xml-platform” mapping=”logical” distinct=”false”>’ +
                                  ‘<entity name=”new_dummy”>’ +
                                    ‘<attribute name=”new_dummyid” />’ +
                                    ‘<filter type=”and”>’ +
                                      ‘<condition attribute=”statecode” operator=”eq” value=”0″ />’ +
                                      ‘<condition attribute=”new_data” operator=”eq” value=”‘ + accountname+ ‘” />’ +
                                    ‘</filter>’ +
                                  ‘</entity>’ +
                                ‘</fetch>’;

 

  • Register plugin classes in the pre and post of the RetrieveMultiple message for the new_dummy entity.
  • Now we execute this fetch from the client side. To check out how can execute a fetch call from client side in Microsoft Dynamics CRM, please refer to my following blog post – https://debajitcrm.wordpress.com/2014/08/01/how-to-execute-retrievemultiple-request-from-javascript/
  • As soon as you fire this fetch, the plugins registered on the pre and post would be triggerd. The following is the code that I have written in the pre-retrivemultiple of this dummy entity and interecepting the query and taking out the account name from the condition,

var organizationServiceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            var pluginContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            var orgService = organizationServiceFactory.CreateOrganizationService(pluginContext.UserId);

            if (pluginContext.InputParameters[“Query”] is FetchExpression
                && pluginContext.MessageName.Equals(“RetrieveMultiple”, StringComparison.OrdinalIgnoreCase)
                && pluginContext.PrimaryEntityName.Equals(“new_dummy”, StringComparison.OrdinalIgnoreCase)
                && pluginContext.InputParameters.ContainsKey(“Query”))
            {
                var fetchExpression = (FetchExpression)pluginContext.InputParameters[“Query”];
                // Convert the FetchXml to QueryExpression.
                FetchXmlToQueryExpressionRequest req = new FetchXmlToQueryExpressionRequest();
                req.FetchXml = fetchExpression.Query;
                FetchXmlToQueryExpressionResponse resp = (FetchXmlToQueryExpressionResponse)orgService.Execute(req);
                var queryExpression = resp.Query;

               

                foreach (var condition in queryExpression.Criteria.Conditions)
                {
                    if (condition.AttributeName.Equals(“new_data”))
                    {

                       // perform what you need to do here. You can get the value passed in the new_data field using condition.values[0]
                    }
                  

                }

          }

 

  • Wondering how would you pass the data back to the caller client side code. Well that’s fairly easy. In the post of retrievemultiple of the dummy entity, populate the BusinessEntityCollection property of the Entity. Below is the code to do the same. And in the responsexml in your client side you can view the entire data. We parsed the response xml to get the list of duplicates and show it to the user in the webresource.

var organizationServiceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            var pluginContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            var orgService = organizationServiceFactory.CreateOrganizationService(pluginContext.UserId);

                var entityCollection = new EntityCollection();

                var entity = new Entity(“de_dummy”);
                entity[“new_dummy1”] = // populate whatever you want to return.

                entityCollection.Entities.Add(entity);

                pluginContext.OutputParameters[“BusinessEntityCollection”] = entityCollection;
         

With this approach you can virtually accomplish anything. One more advantage of this approach is you can run these plugins under higher privileged users and perform operation with that user.

Hope this helps!

Advertisements

Author: Debajit

I am a Dynamics CRM Most Valuable Professional (MVP) with 10 years of experience in Microsoft .NET Technologies and 7 years of dedicated experience in Microsoft Dynamics CRM. I have worked with companies like Microsoft, SanDisk, PwC, TMF Group and have extensive experience of implementing complex CRM solutions from both offshore and client side. Currently the face of XrmForYou.com with significant experience in delivering corporate training on Dynamics CRM and have already delivered multiple projects to client through XrmForYou.com Author of multiple tools on codeplex including the 'Role Based Views' and 'CRM-Sharepoint Metadata manager & Attachment Extractor' which are available for commercial use under XrmForYou.com For consulting/ training, drop me a note at info@xrmforyou.com or visit our website www.xrmforyou.com

6 thoughts on “Call plugin from Javascript in Microsoft Dynamics CRM.”

  1. It’s really good. BUT with CRM 2013 we have got Actions that could be handled with plugins. We don’t need anymore to design some logic and pack data in fields e.t.c. to call server side code. Seems that you’ve build own bicycle.

    1. Hi Andrii,
      thanks a lot for reading my blog and appreciating it.
      Couple of points here

      1. Yes you are right. this can be achieved by Actions in CRM 2013. But there are scenarios where you need to run your code under higher privileges and there plugins would be the only approach to impersonate the high privileged user. Actions I guess would run under the calling user’s context only. Please correct me if I am wrong here (not explored actions in and out)

      2. In 2011 version, with the absence of actions, this would be the only approach

      1. In case you want to run server side code under a context of privileged user just instantiate CRM Service with null as a parameter like following (anyway your code works in a context of a calling user 😉 ):
        var orgService = organizationServiceFactory.CreateOrganizationService(null);

        In CRM 2011 – yes. That is correct that this was One of ways to call server side code. But who delivers now (2014 year outside) projects based on CRM 2011? May be only projects that are on support.

      2. Thanks Andrii.
        The code worked for me always in plugins. But in CRM 2013 when I used a custom workflow activity from an action, no matter what I passed in the userid parameter, it always created the organizationservice under the calling user’s context only. I will surely give this a try and let you know. Thanks for your comments.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s