Moin,
das CrmFetchKit findet Ihr jetzt auch auf CodePlex: http://crmfetchkit.codeplex.com/
Have fun!
Daniel
Moin,
das CrmFetchKit findet Ihr jetzt auch auf CodePlex: http://crmfetchkit.codeplex.com/
Have fun!
Daniel
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
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
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:
Nachteile:
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
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:
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:
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: