In der kommenden Blog-Serie möchte ich euch gemeinsam mit meinem Kollegen ZhengChen Guan die Alpha-Version einer Open-Source-Softwarebibliothek vorstellen, die ich im Laufe des letzten Jahres entwickelt, verfeinert und bereits in einigen Projekten einsatzerprobt habe. Dabei handelt es sich um einen Client, mit dem ihr unter .NET Core gegen die Web API von Dynamics365 CRM programmieren könnt. Der Quellcode hierzu ist auf GitHub
veröffentlicht.
Die Serie gliedert sich in drei Teile:
Motivation
Für die konventionelle Programmierung gegen Dynamics365 CRM bietet Microsoft das Microsoft.Xrm.Sdk
unter dem bereits in die Jahre gekommenen .NET Framework an. Darin enthalten sind neben Klassen für die Arbeit mit Entitäten auch solche, mit denen die Authentifizierung, Kommunikation und Ausführung von CRUD-Operationen bewerkstelligt werden können. Mit dem Fortschritt auf .NET Core hat Microsoft allerdings eine Lücke in der eigenen Systemwelt hinterlassen, da das SDK für .NET Core Anwendungen nicht nutzbar ist. Seither braut hier jeder bei Bedarf sein eigenes Süppchen und wir haben uns an dieser Stelle eine allgemeingültige und wieder verwendbare Lösung gewünscht. Die eigens entwickelte Softwarebibliothek löst genau dieses Problem– durch sie erfolgt nun auch das Enabling von .NET Core Anwendungen für den Umgang mit Datensätzen aus Dynamics365 CRM.
Funktionsweise
Die Kommunikation zwischen Client und CRM erfolgt über die Dynamics365 CRM Web API. Der Client arbeitet dabei nach dem ORM-Prinzip, so dass Klassen und Eigenschaften im Code auf entsprechende Tabellen und Spalten des Dataverse abgebildet werden können. Die Models müssen vom Benutzer selbst – abhängig vom Customizing der eigenen Instanz – erbracht werden. Dabei wird vorrangig deklarativ mit Klassenattributen und JSON-Annotationen gearbeitet. Neben generischen Methoden für alle gängigen CRUD-Operationen deckt der Client zusätzlich die Authentifizierung der Anwendung ab.
Features
- Integrierte Authentifizierung über OAuth 2.0 Client Credential Flow mit Client-Id & Secret
- Create, Retrieve, Update, Delete von Datensätzen aus Dataverse inkl. Upsert und RetrieveMultiple
- Unterstützung aller durch das System erlaubten OData-Kommandos (z.B. Filter, Select, Expand)
- Transaktionssichere Ausführung mehrerer CRUD-Operationen mit einer HTTP-Anfrage über OData Batch-Requests
Einsatzbereiche
Der Client bietet sich vor allem im Bereich der Integrationslösungen mit Dynamics365 CRM an. Konkrete Anwendungsfälle könnten sein:
- Eure ASP .NET Core Web-Anwendung benötigt Stammdaten wie Firmen oder Kontakte, die aus Dynamics365 CRM abgerufen werden müssen
- Eure Azure Function v3 unter .NET Core soll Aufgaben an Verkaufschancen erstellen und verknüpfen
- Eure Geschäftslogik muss aufgrund von Plattformlimitierungen (z.B. Massenerstellung von Datensätzen) auf die Azure Plattform ausgelagert werden, aber ist zu komplex für die Umsetzung in einem Flow
Ein kleines Praxisbeispiel dazu:
Der Geschäftsprozess eines Kunden sah die Umwandlung von Angeboten aus Sales in Arbeitsaufträge des Field Service vor. Die einzelnen Angebotspositionen aus dem Angebot mussten dabei automatisiert auf Arbeitsauftragspositionen abgebildet werden. Die Regelsätze der Konvertierungslogik waren dabei so komplex und umfangreich, dass die Abbildung der Logik in einem Flow nicht denkbar gewesen wäre [1]. Eine weitere Schwierigkeit bestand zudem darin, dass sich die Anzahl der zu erstellenden Positionen erwartungsgemäß auf mehrere Hunderte belief. Die programmatische Erstellung dieser Datensätze aus einem Plugin heraus hätte die zeitliche Ausführungsbeschränkung von 2 Minuten in vielen Fällen überschritten. Die Logik musste also – auch auf Empfehlung von Microsoft
hin – auf die Azure Cloud Plattform ausgelagert werden. Wir entschieden uns in diesem konkreten Fall für eine .NET Core Azure Function v3 und konnten dort mit Hilfe des Clients alle nötigen Operationen für die betroffenen Datensätze effizient durchführen.
[1] Bei dieser Entscheidung hat mir die Entscheidungshilfe
aus einem meiner früheren Blog-Beiträge geholfen. Schaut doch mal rein!
Ein Vorgeschmack zum Abschluss
Der Deep Dive zur Funktionsweise und Benutzung des Clients mit umfänglichen Beispielen folgt im nächsten Teil der Serie. Als kleine Anregung jedoch vorab schon mal ein kleiner Ausschnitt, wie die Erstellung eines Firmendatensatzes in Dynamics365 CRM später im Code aussehen könnte.
Zunächst müsst ihr eine Datenklasse für eure Tabelle mit den für euch relevanten Feldern erstellen. Keep it simple – uns interessiert nur der Name. Mehr zu den Details und Einzelheiten dann im kommenden Teil 2.
[DataverseTable("account", "accounts")]
public class Account
{
[DataverseRowId]
[JsonPropertyName("accountid")]
public Guid Id { private get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
}
Unter der Annahme, dass bereits eine authentifizierte und verbundene Instanz des Clients im Platzhalter client vorliegt (auch hierzu mehr in Teil 2), legen wir in Dynamics365 CRM einen neuen Firmendatensatz an.
await client.CreateAsync(new Account
{
Name = "Objektkultur Software GmbH"
});