Monthly Archives: November 2012

Dynamics CRM: get all updated fields in javascript

I got somewhat strange form behaviour in Dynamics CRM this morning – for whatever reason, at attempt to close one of the phone call records kept brining up a “do you want to save the updates?” dialog. It did not seem to matter that there were no updates, and, even once all the javascripts have been removed, this strange behaviour went on.

I figured that I may need to see which field is causing this, so, here is a javascript code snippet which does this job – if you run into a similar situation, just add a web resource with this code, and, then, add a call to showDirtyAttributes to the “onSave” event of your form:

function showDirtyAttributes()
{
var names = “”;
Xrm.Page.data.entity.attributes.forEach(function(attribute, index)
{
if(attribute.getIsDirty())
{
names += attribute.getName()+”;”;
}
});
alert(names);
}

It actually helped – to some extent. It turned out one of the lookup fields did not like the reference assigned to it for some reason. It did work, I could navigate from that field to the referenced record.. However, I had to update that referenced record and choose it for the lookup once again to finally get rid of the “do you want to save the updates?” dialog.  I’m still wondering what was so unique about that record, though..

Dynamics CRM: You can.. call a plugin from javascript.

It’s been generally accepted that Dynamics CRM does not allow us to call plugins from javascripts. And, generally speaking, we can’t call just any plugin from javascript. However, we can still make use of CRM plugins in a little unusual way.

Here is the scenario: there is a client-side java script, and we need to:

– Initiate some server-side processing

– Get the results of that processing back to our javascript

A potential solution to that might be to implement a web service which would encapsulate server-side logic, and to call that web service from our javascript. That might not work with Dynamics CRM online since we can’t deploy our web service on the CRM server, and, so, we may end up with a cross-domain call from our javascript. That’s not to mention that we’ll need to deploy our web service somewhere.

As of now, the only type of server-side processing we can use in Dynamics CRM online is called “plugins”, though. So, can we use CRM plugins in the scenario described above?

Surprisingly, the answer is yes.

First of all, there is a straightforward solution. We might register a plugin which would kick in whenever a new record of specific type is created. We might create a record of that type using javascript; we might pass some parameters to the plugin through the record fields; and, then, we might get the results back through another record (which would be created by the plugin). Would it work? I guess it would. However, we’ll have to work around possible concurrent calls, and, in general, I don’t like the idea of having to store intermediate results in CRM database.

There is another solution which still requires a dedicated entity type, but no CRM records of that type will ever have to be created. Here is how it works:

  • We need an entity to pass data from our plugin to javascript
  • We need to register a post-operation plugin on “RetrieveMultiple” for that entity
  • We also need to register a pre-operation plugin on “RetrieveMultiple” for that entity
  • Finally, we need to have a javascript that will make retrievemultiple request to CRM using fetchxml. That fetchxml will basically ask CRM to return all records of our entity type, and it will also pass whatever parameters we need to pass to the plugin through fetchxml conditions

The point is: such a request from the javascript will activate both of the plugins (pre/post operation). In the pre-operation plugin, we will extract request parameters from fetch xml conditions. In the post-operation plugin, we will populate context.OutputParameters[“BusinessEntityCollection”] with the fictitious records. As a result, our javascript will receive those records, and that’s how it will get data from the plugin. That’s when we’ll have our mission accomplished – we will have a javascript which uses CRM plugins to do server-side processing, yet we will not have to store any data in CRM.

The reason we need two plugins in this scenario is that we don’t have access to the fetch xml in our post-operation plugin, although we still need a post-operation plugin to create results for the javascript.

Basically, all we have to do in the pre-operation plugin is to extract request parameters from the fetch xml and pass those parameters to the post-operation plugin through the SharedVariables collection of plugin context.

In the post-operation plugin, we can do whatever server-side processing we need to do (based on the request parameters that we’ve already extraced in the pre-operation), and, once it’s done, we can populate [“BusinessEntityCollection”] member of the context output parameters collection (in case with this property, we can’t do it in pre-operation.. so, again, we need both pre and post-operation plug-ins in this scenario).

Just to add a bit more clarity, here is a quick diagram:

image

Finally, here is a real-life scenario where I used this approach:

  • My client wanted to implement javascript-based “behind the scenes” address verification with QAS (qas.com)
  • QAS web service is hosted on QAS server, so any attempt to use javascript to call that service ends up with a cross-domain call
  • On the other hand, it’s not a problem at all to implement that sort of verification in C#

This fits the scenario described above quite nicely. I have a javascript that makes retrieve mutliple request using fetch xml. There are two plugins on the CRM side. Pre-operation plugin extracts address details from fetch xml. Post-operation plugin makes a call to QAS web service, and, depending on the results of that call, creates a fictitious record  (that record never gets stored in CRM), adds that record to the BusinessEntityCollection, and that’s how my javascript receives the results back.