27. Juni 2016 · von Andreas Klein

CRM Plugins aus JavaScript heraus triggern

CRM Plugins werden typischerweise beim Erstellen, Ändern oder Löschen eines Datensatzes ausgeführt. Dies kann man sich zu nutze machen, um via JavaScript einen serverseitigen Code auszuführen, indem man mit Hilfe des XRM Service Toolkits einen Datensatz im CRM erstellt und damit ein Plugin triggert.

Die Grundidee ist denkbar einfach: Wir erstellen ein Plugin, welches auf den Create-Event eines Datensatzes reagiert. In diesen Datensatz schreiben wir via Javascript was wir tun möchten. Das Plugin reagiert auf den Pre-Create Event und führt den entsprechenden Plugin Code aus. Der Returnwert wird dann vom Plugin in den Datensatz mit eingefügt und das aufrufende JavaScript kann diesen auslesen und weiterverarbeiten.

Dazu benötigen wir:

  • eine CRM Entity, welche die Definition des auszuführenden Codes enthält,
  • eine CRM Entity für die Aufrufe,
  • ein CRM Plugin, welches auf das Erstellen neuer Datensätze reagiert und
  • eine JavaScript Library, welche die Plugin-Calls enthält.

Das folgende Bild veranschaulicht den Aufbau und Kommunikationsfluss:

Gate4 CRM Command

 

Um die Lösung möglichst generisch zu gestalten, legen wir in einer „Command Definition“ Entity fest, welche die zu instantiierende Klasse und aufzurufende Methode definiert. Damit hier die Kommunikation funktioniert, muss die betreffende Klasse einen Konstruktor bereitstellen, welcher das IOrganizationService sowie das ITracingService Objekt entgegen nimmt. Die Methode, welche dann ausgeführt wird, muss als Parameter einen String entgegennehmen und als Ergebnis einen String zurück liefern.

public string MethodToCall(string json)
{
   ...
}

 

Dabei eignet sich zur Parameterübergabe im String natürlich das JSON Format, weil wir dies aus dem aufrufenden JavaScript einfach erzeugen können bzw. ein Ergebnis im JSON Format einfach weiterverarbeiten können.

In der „Command Definition“ legen wir neben einem Namen über den das Command aufgerufen wird auch die zu instantiierende Klasse und die aufzurufende Methode fest. Über den Status kann später gesteuert werden, ob das Command aktiv oder deaktiviert ist.

Gate4 CRM CommandDefinition

 

Zum Aufruf des Commands erzeugt man nun via JavaScript einen „Command Call“ Datensatz. Dazu haben wir den Aufruf in einer JavaScript Bibliothek gekapselt:

 var parameterJson = { "PricelistId": ItemId, "Name": result.name };
 pricelevelId = Gate4.Command.Execute("ClonePricelist", JSON.stringify(parameterJson));
 if (pricelevelId != null) {
   Xrm.Utility.openEntityForm("pricelevel", pricelevelId);
 }

 

In dem Beispiel liefert das Command die ID eines neu erstellten Datensatzes zurück und via Javascript wird dieser dann sofort angezeigt.

Die Gate4.Command.Execute Function handelt die Erstellung des Command Call und das Auslesen der Rückgabewertes:

var execute = function (commandName, parameter) {
  var fetchXml = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>" +
                   "<entity name='g4_command'>" +
                     "<attribute name='g4_name' />" +
                     "<attribute name='statecode' />" +
                     "<attribute name='g4_commandid' />" +
                     "<filter type='and'>" +
                       "<condition attribute='statecode' operator='eq' value='0' />" +
                       "<condition attribute='g4_name' operator='eq' value='"+commandName+"' />" +
                     "</filter>" +
                   "</entity>" +
                 "</fetch>";
  var retrievedCommands = XrmServiceToolkit.Soap.Fetch(fetchXml);

  if (retrievedCommands.length != 1) return null;

  var entity = new XrmServiceToolkit.Soap.BusinessEntity("g4_commandcall");
  entity.attributes["g4_callid"] = guid();
  entity.attributes["g4_parameter"] = parameter;
  entity.attributes["g4_commandid"] = { id: retrievedCommands[0].id, logicalName: retrievedCommands[0].logicalName, type: 'EntityReference' };

  var commandCallId = XrmServiceToolkit.Soap.Create(entity);

  var cols = ["g4_result"];
  var retrievedCommandCall = XrmServiceToolkit.Soap.Retrieve("g4_commandcall", commandCallId, cols);

  return retrievedCommandCall.attributes["g4_result"].value;
};

 

Im CRM triggert dies nun einen Pre-Create Plugin für die CommandCall Entity.

Gate4 CRM Command Plugin Registration

 

Das Command Plugin liest dann die Definition zu dem betreffenden Command aus und instantiiert mittels Reflection ein Objekt und führt die entsprechende Methode aus:

AttributeCollection attributes = ((Entity)localContext.PluginExecutionContext.InputParameters["Target"]).Attributes;
string parameter = attributes["g4_parameter"].ToString();
EntityReference commandReference = (EntityReference)attributes["g4_commandid"];

Entity command = new Entity("g4_command");
ColumnSet attributeSet = new ColumnSet(new string[] { "g4_class", "g4_function", "statecode" });
command = localContext.OrganizationService.Retrieve(command.LogicalName, commandReference.Id, attributeSet);

if (((Microsoft.Xrm.Sdk.OptionSetValue)command["statecode"]).Value == 0)
{
  Assembly assembly = Assembly.GetExecutingAssembly();
  Type type = assembly.GetType(command["g4_class"].ToString());
  MethodInfo methodInfo = type.GetMethod(command["g4_function"].ToString());
  ConstructorInfo constructorInfo = type.GetConstructor(new Type[] { typeof(IOrganizationService), typeof(ITracingService) });
  object classInstance = constructorInfo.Invoke(new object[] { localContext.OrganizationService, localContext.TracingService });
  object s = methodInfo.Invoke(classInstance, new Object[] { attributes["g4_parameter"].ToString() }); 
  string status = s != null ? s.ToString() : "";
  attributes.Add("g4_result", status);
}

 

Um nun ein weiteres Command bereitzustellen, benötigen wir lediglich eine Klasse mit oben beschriebenem Konstruktor und eine entsprechende Methode sowie einen Eintrag in der Command Definition. Danach kann dieses serverseitige Plugin mittels der Gate4.Command Javascript Library einfach vom Client aus angestoßen werden.

 

In einem folgenden Artikel stelle ich unsere Lösung zum Clonen von Preislisten im CRM vor, welche von diesem Mechanismus in Verbindung mit den Modalen Dialogen in CRM Gebrauch macht.



Diesen Blogeintrag bewerten:


Haben Sie Fragen zu diesem Artikel oder brauchen Sie Unterstützung?

Nehmen Sie mit uns Kontakt auf!

Wir unterstützen Sie gerne bei Ihren CRM-Vorhaben!


Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Kontakt
Lassen Sie sich von uns beraten
Wir freuen uns über Ihr Interesse an unseren Leistungen. Hinterlassen Sie
uns Ihren Namen, Ihre Telefonnummer und E-Mail Adresse – wir melden
uns schnellstmöglich bei Ihnen.
Kontakt aufnehmen