CrmRestKit.js Version 2.0

Moin,

auf Codeplex findet ihr jetzt die neuste Version vom CrmRestKit. Wie der gute Daniel Cai gestern via Twitter verkündet hat, gibt es bereits ein anderes Framework, welches das CrmServiceToolkit ablösen soll bzw. auf 2011 portiert hat. Das XrmServiceToolkit unterstützt sowohl REST also auch SOAP!

http://xrmservicetoolkit.codeplex.com
http://jaimiescode.blogspot.com/2012/02/introduction-xrmservicetoolkit-crm-2011.html

So, was nun sprach Zeus. Was ist jetzt besser? XrmServiceTookit vs. CrmRestKit? Nun man muss sagen, das der Umfang der Methoden beim XrmServiceToolkit erheblich höher ist. Für das CrmRestKit spricht letztlich nur die Lazy-loading Methoden und die (meiner Meinung nach) einfacheren API und natürlich die Verwendung von Promise/A 🙂

Daniel

FetchUtil.js -> CrmFetchKit.js

Moin,

am Donnerstag bin ich per Zufall auf FetchUtil.js von Customer Effective gestoßen. Zusammen mit den Ausführungen in diesem Blog-Eintrag kann man also wieder schön fetchxml gegen die neuen WCF Services von Dynamcis CRM feuern.

Der Aufbau des Quellcodes und die Verwendung der Library finde ziemlich umständlich (man  muss für jede Anfrage per „new“ eine neue Instanze erzeugen). Also hab ich mich am Freitag mal daran versucht die Library etwas aufzuräumen und dann auch noch das Future/Promise Pattern einzubauen. Letztes finde ich besonders wichtig, damit die „aufgeräumte“ Version schön mit dem CrmRestKit kombiniert werden kann. Ziel ist der neben der einfachen Fetch Methode auch noch ein paar andere Methoden bereitzustellen, z.B.: GetByAttribute() oder GetById().

Sobald alles läuft werde ich den Quellcode hier veröffentlichen.

Grüße

Daniel

CrmRestKit 2.0

Moin,

ich arbeite gerade an der nächsten Version des CrmRestKit für Dynamics CRM 2011. Bei diesem Framework handelt es sich um eine Protierung des sehr guten CrmServiceToolkit (http://crmtoolkit.codeplex.com/) von Daniel Cai.

Die Library soll das ausführen von einfachen CRUD (Create Read Update Delete) Operationen via JavaScript vereinfachen. Die Frage ist jetzt warum eine Portierung überhaupt erforderlich ist, zumal der Funktionsumfang vom CrmServiceToolkit umfangreicher ausfällt. Neben den einfachen CRUD Operationen werden auch noch folgende unterstützt:
– SetState
– Assign
– Associate
– Disassociate

Die Portierung ist deshalb erforderlich da CrmServiceTookit auf die „alten“ CRM WebServices (.asmx) zugreift und die Services als deprecated markiert wurden. Hinzukommt das Problem das ein Error-Handling bei asynchronen Request bei Verwendung des CrmServiceToolkits nicht möglich ist: Man kann lediglich einen callback definieren der im Erfolgs-Fall aufgerufen wird, für den Fall das ein Fehler auftritt  kann man keinen callback definieren (und try-/catch läuft nicht bei asyn. Requests).

Im Gegensatz zum CrmServiceToolkit basiert das CrmRestKit auf OData (bereitgestellt durch die neuen WCF Servies) und nicht auf SOAP, was mit einer Reihe von Vorteilen und leider auch mit einer Latte von Nachteilen:

Vorteile:

  1. JSON: Die Daten werden direkt als JSON Object gefiefert und mittel JSON2.js kann man somit direkt in JavaScript Object überführen.
  2. Fast: Ich hab leider keine Performance Tests zu Hand, aber gefühlt sind die Requests mittels OData nen guten Zacken schnell.
  3. Zukunft: Wenn man das SDK heranzieht werden wohl die Zukünftigen Versionen von Dynamcis CRM mehr und mehr auf OData basieren.

Nachteile:

  1. FetchXml: Leider kann man die Abfragen nicht mehr mit FetchXml formulieren, was wirklich schade ist, da ich mich in den letzten Jahren doch sehr an FetchXml gewöhnt hatte.
  2. No-Count: Manche Funktionen der OData Definiton werden von Dynamics CRM 2011 derzeit noch nicht unterstützt, dazu gehört leider auch „count“.
  3. Limit: Bestimmte Operationen können derzeit noch nicht mittel OData druchgehöhrt werden:
    – Assign
    – SetState
    – Associate
    – DeAssociate

So jetzt zum Eingemachten: Ganz fertig ist die Library noch nicht, aber derzeit basiert es auf folgenden Komponenten:

– jQuery-1.7.2.js
– JSON2.js

Da jQuery eine wunderbare Unterstützung für das Promise Pattern (http://www.erichynds.com/jquery/using-deferreds-in-jquery/) bietet verwendet auch das CrmRestKit diesen Ansatz. Damit ist es möglich Abfragen wie folgt zu formulieren:

CrmRestKit.Retrive('Account', id, ['Name', 'EmailAddress'])
   .done(function(){ /* success-callback */})
   .fail(function(){ /* error-callback */});

Standardmäßig werden alle Request async. durchgeführt, sollte man jedoch ehr sync. bevorzugen, kann wie folgt vorgehen:

CrmRestKit.Retrive('Account', id, ['Name', 'EmailAddress'], true)
   .done(function(){ /* success-callback */})
   .fail(function(){ /* error-callback */});

Auf Codeplex findet sich derzeit noch die alte Version (http://crmrestkit.codeplex.com/), wenn ich aber die Zeit finde und die Lib. schön funktioniert und alle Unit-Test (QUnit kann ich nur empfehlen) passen werde ich den Code dort wieder hosten.

Daniel

Dynamics CRM Coding Conventions

Moin,

so wollen wir doch mal den ersten „sinnvollen“ Beitrag erstellen:

Bei größeren Dynamics CRM Projekten habe ich schmerzlich die Erfahrung gesammelt das einheitliche coding-convetions zwar durchaus für den Plugin-Code angewendet werden, jedoch bei JavaScript gerne alle Hemmungen fallen gelassen werden und jeder munter durcheinander programmiert, was recht schnell zu ganz besonders ärgerlichen Problem führen kann.

Coding-Conventions können uns dabei helfen einheitliche Muster zu definieren die sowohl die Wartbarkeit (von der Lesbarkeit mal ganz zu schweigen) als auch die Wiederverwendbarkeit erheblich zu steigen. Sagen will mal wir möchten ein einfaches Script schreiben das, auf ein bestimmtes Event der Contact Form registriert ist.

Die erste Entscheidung die wir treffen müssen ist wo der Code abgelegt wird. Eine Möglichkeit wäre es (zumindest in CRM 2011) ein neue .js Datei anzulegen und diese als WebResources in CRM zu laden und mit dem entsprechenden onChange Event der Entität zu verknüpfen. Ich bin allerdings ein groß Freund davon für jede Entität ein zentrales Script anzulegen das zentral alle Client-Seitigen Anpassungen verwaltet. D.h. es gibt erstmal nur eine .js Datei (onload.contact.js) für die für das onLoad Event registriert ist.

Die onload.contact.js Datei beinhaltet dann folgenden Code:

///
/// OnLoad Script for the entity 'contact'
///
/// requires(jquery.1.7.1.js, underscore.1.2.3.js)
///
var contact = (function(){

    ///
    /// Private member
    ///

    ///
    /// Invoked by the crm runtime on page-load
    ///
    function Init(){

        switch (Xrm.Page.ui.getFormType()) {

            case 1: // Create
                // ...
                break;

            case 2: // Update
                // ...
                break;
        }
    };

    ///
    /// Is invoked for serveral attribute (see entity-form definition)
    ///
    function GenericOnChange(executionContext) {

        // get the attribute that triggers the event
        var attrname = executionContext.getEventSource().getName();

        switch (attrname) {

            case 'foo_fancy_attr':
                // ....
                break;
        }
    };

    ///
    /// Public API
    ///
    return {
        Init: Init,
        GenericOnChange : GenericOnChange
    };
}());

In JavaScript gibt es leider keine direkte Möglichkeit Namespaces zu definieren, was häufig dazu führt das der global Namespace unnötiger Weise mit variablen belastet wird. Verwendet man jedoch den Ansatz der „self-invoking function“ kann man diese Problem umgehen. Stark vereinfacht gesagt erlaubt es dieses Pattern die Definition eines Objects welches über public und private Methoden verfügt. Private Methoden werden einfach innerhalb des Funktionskörpers definiert und lediglich die öffentlichen werden in dem „return Object“ verwendet. Der Code erzeugt ein JavaScript Module das über zwei public Member verfügt:

  1. Init
  2. GenericOnChange

Ok, zurück zur Aufgabenstellung. Soll nun eine bestimmte Logik (z.B.: Validierung) durchgeführt werden, müsste man lediglich das Script mit dem OnLoad Event Verknüpfen und im OnChange Event auf die generische Methode verweisen:

OnLoad Event Definition

Vorteil diese Ansatzes ist es das Änderungen (z.B.: weitere Methoden sollen aufgerufen werden) nur im Code vorgenommen werden müssen und nicht in der CRM UI. Darüberhinaus muss man nicht in der Oberfläche nach der JavaScript Logik für ein bestimmtes Event suchen, sonder man muss nur die onload-js Datei konsultieren.

Zusammenfassend kann man aus dem obigen Code folgende Konventionen ableiten:

  1. Datei Name: Der Name der .js Datei sollte immer Aufschluss über den Anwendungsfall und die zugehörige Entität geben (onload.contact.js, ribbo.foo.contact.js, …)
  2. Die Methode die vom CRM aufgerufen wird, sollte immer den Namen „Init“ tragen. Damit wird es für andere Team-Mitgelieder einfacher den Aufbau der Datei nachzuvollziehen.
  3. Module ermöglichen eine einfache Trennung zwischen public und privte Methoden.
  4. Referenzierte Module /Libraries werden im Module Kommentar erfasst (/// requires(jquery.1.7.1.js, underscore.1.2.3.js)) . Damit ist sichergestellt das Abhängigkeiten erkannt und berücksichtigt werden können.