Schreiben eines Plug-Ins

Sie können mit einer der folgenden Methoden Plug-Ins erstellen:

  • Power Platform Entwicklungstools bieten eine moderne Möglichkeit, Plug-Ins zu erstellen. Bei den Tools, auf die hier verwiesen wird, handelt es sich um Power Platform Tools für Visual Studio und Power Platform CLI. Diese beiden Power Platform Tools generieren ähnlichen Plug-In-Code, sodass die Umstellung von einer Toolmethode auf die andere ziemlich einfach und nachvollziehbar ist.

    • Verwenden Sie Power Platform Tools für Visual Studio, um schnell Vorlagen-Plug-In-Code zu erstellen und ein Plug-In zu registrieren (bereitzustellen). Ein Schnellstart-Artikel ist verfügbar, der Ihnen zeigt, wie das geht. Verwenden Sie dieses Tool, wenn Sie in Visual Studio arbeiten möchten.

    • Verwenden Sie Power Platform CLI, um ein einfaches (Visual Studio kompatibles) Plug-In-Projekt mit Plug-In-Codevorlage mit einem einzigen pac plugin Befehl zu erstellen. Anschließend verwenden Sie interaktiv das Tool zur Plug-In-Registrierung mit dem Befehl pac tool prt, um das Erstellen bei Microsoft Dataverse zu registrieren. Verwenden Sie dieses CLI-Toolset, wenn Sie gerne in einem Terminalfenster oder Visual Studio Code arbeiten.

  • Schreiben Sie Code manuell mit Visual Studio oder Ihrem bevorzugten Editor. Dieser Artikel konzentriert sich auf das Schreiben von Code mit Dataverse-APIs, die vorgestellten Konzepte gelten jedoch auch für die Plug-In-Entwicklung mit unseren zuvor erwähnten Tools.

IPlugin-Schnittstelle

Ein Plug-In ist eine kompilierte Klasse in einer Assembly, die für .NET Framework 4.6.2 erstellt wurde. Jede Klasse in einem Plug-in-Projekt, die auf einem Ereignis Pipeline Schritt registriert ist, muss die Schnittstelle IPlugin implementieren, die eine einzelne Methode IPlugin.Execute definiert.

public class MyPlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        throw new NotImplementedException();
    }
}

Die Execute-Methode akzeptiert einen einzelnen IServiceProvider-Parameter. Der IServiceProvider hat eine einzelne Methode: GetService. Verwenden Sie diese Methode, um verschiedene Typen von Diensten abzurufen, die Sie in Ihrem Code verwenden können.

Weitere Informationen: Dienste, die Sie in Ihrem Code verwenden können

Wichtig

Bei der Ableitung vom IPlugin sollte die Klasse statusfrei geschrieben sein. Dies liegt daran, dass die Plattform eine Klasseninstanz zwischenspeichert und sie aus Leistungsgründen erneut verwendet. Eine einfache Möglichkeit, sich dies vorzustellen, besteht darin, dass Sie keine Eigenschaften oder Methoden der Klasse hinzufügen sollten, und alles sollte in der Execute-Methode eingeschlossen sein.

Wenn zur Plug-In-Erstellung die Power Platform Tools-Erweiterung oder Power Platform CLI verwendet wird, implementiert die generierte PluginBase-Klasse die IPlugin-Schnittstelle.

Es gibt einige Ausnahmen von der Aussage über das Hinzufügen von Eigenschaften oder Methoden im obigen Hinweis. Sie können zum Beispiel eine Eigenschaft haben, die eine Konstante darstellt, und Sie können Methoden haben, die von der Execute Methode aufgerufen werden. Es ist wichtig, dass Sie nie irgendeine Serviceinstanz oder Kontextdaten als Eigenschaft in Ihrer Klasse speichern. Diese Werte ändern sich bei jedem Aufruf, und Sie möchten nicht, dass diese Daten zwischengespeichert und auf darauf folgende Aufrufe angewendet werden.

Weitere Informationen: Entwickeln von IPlugin-Implementierungen als statusfrei

Konfigurationsdaten Ihrem Plug-In übergeben

Wenn Sie ein Plug-in registrieren, können Sie optional Konfigurationsdaten angeben, die zur Laufzeit an das Plug-in übergeben werden. Konfigurationsdaten ermöglichen es Ihnen zu definieren, wie eine bestimmte Instanz eines registrierten Plug-In sich verhalten soll. Diese Informationen werden als Zeichenfolgendaten den Parametern im Konstruktor Ihrer Klasse übergeben. Es gibt zwei Parameter namens unsecure und secure. Verwenden Sie die ersten unsecure-Parameter für Daten, bei denen es Ihnen nichts ausmacht, wenn andere sie sehen können. Verwenden Sie den zweiten secure-Parameter für vertrauliche Daten.

Der folgende Code zeigt die drei möglichen Konstrukteursignaturen für eine Plug-In-Klasse namens MyPlugin.

public MyPlugin() {}
public MyPlugin(string unsecure) {}  
public MyPlugin(string unsecure, string secure) {}

Die sicheren Konfigurationsdaten werden in einer separaten Tabelle gespeichert, die nur Systemadministratoren lesen dürfen.

Weitere Informationen: Registrieren des Plug-In-Schritts > Konfigurationsdaten festlegen

Abstrakte PluginBase-Klasse

Der PluginBase-Klasse implementiert die IPlugin-Schnittstelle. Wir bieten diese Klasse an, da sie ein robustes Programmiermuster implementiert, das sich in kommerziellen Lösungen bewährt hat. Die Verwendung dieser Klasse in Ihrem Plug-In-Code wird empfohlen, ist jedoch optional.

Die Klasse ist in keiner SDK-Assembly verfügbar, sondern Sie müssen die Klasse mit einem unserer Tools generieren. Um die Klasse zu generieren, erstellen Sie ein Plug-In-Projekt in der Power Platform Tools-Erweiterung für Visual Studio oder führen Sie den Power Platform-CLI-Befehl pac plugin init aus. Im generierten Projekt finden Sie eine PluginBase.cs-Datei.

Weitere Informationen: pac-Plug-In, Schnellstart: Ein Plug-In mit Power Platform Tools einrichten

Wichtig

Die von der Power Platform Tools-Erweiterung generierte PluginBase-Klasse und die Power Platform-CLI weisen leicht unterschiedliche Klassenmitgliedssignaturen auf. Es ist am besten, sich für die eine oder das Möglichkeit zu entscheiden und während der gesamten Entwicklung Ihres Plug-In-Codes dabei zu bleiben. Beide Versionen der Klasse haben die gleiche Funktionalität und funktionieren ähnlich.

Dieses Klassendiagramm bietet eine visuelle Darstellung der wichtigsten Schnittstellen und Klassen im Zusammenhang mit PluginBase.

PluginBase-Klasse und andere verknüpfte Typen.

Die Plugin1-Beispielklasse (im Diagramm) leitet sich von PluginBase ab. Sie geben dieser Plugin1-Klasse normalerweise Ihren eigenen benutzerdefinierten Namen und fügen Code hinzu, um die ExecuteDataversePlugin-Methode und den Klassenkonstruktor zu implementieren. Die LocalPluginContext-Klasse wird automatisch mit den angegebenen Dienstreferenzen und Endpunkten initialisiert, die für Ihr Plug-In verfügbar sind. Wenn Sie die IPlugin-Schnittstelle implementieren würden, müssten Sie Code schreiben, um alle diese Dienste und Endpunkte vor der Verwendung zu initialisieren.

Dienste, die Sie in Ihrem Code verwenden können

Normalerweise müssen Sie in Ihrem Plug-In:

  • Auf die an Ihr Plug-In übergebenen Kontextdaten zugreifen, um Informationen über die Entität und die Nachrichtenanforderung herauszufinden, die das Ereignis verursacht und Ihr Plug-In aufgerufen hat. Diese Daten werden als Ausführungskontext bezeichnet.
  • Greifen Sie mit SDK für .NET-Aufrufe auf den Organisationswebdienst zu, um Meldungsanforderungsvorgänge wie Abfragen, Erstellen, Aktualisieren, Löschen und mehr auszuführen.
  • Schreiben Sie Meldungen an den Ablaufverfolgungsdienst, sodass Sie auswerten können, wie Ihr Plug-In-Code ausgeführt wird.

Hinweis

Alle Dataverse-Dienste, die Ihr Plug-In normalerweise nutzen würde, und der Plug-In-Ausführungskontext sind vorkonfiguriert und für Ihren Plug-In-Code verfügbar, wenn Sie Ihr Plug-In von der PluginBase-Klasse ableiten.

Im IServiceProvider.GetService Methode bietet Ihnen eine Möglichkeit, bei Bedarf auf Dienstverweise zuzugreifen, die im Ausführungskontext übergeben werden. Um eine Instanz eines Dienstes zu erhalten, rufen Sie die Methode GetService auf und übergeben den Typ des Dienstes. In den nächsten Abschnitten erfahren Sie mehr über diese Methode.

Context-Ausführungen

Der Ausführungskontext enthält eine Fülle an Informationen, die ein Plug-In vielleicht braucht. Der Kontext wird mit dem folgenden Code abgerufen.

IPluginExecutionContext context = (IPluginExecutionContext)
    serviceProvider.GetService(typeof(IPluginExecutionContext));

Weitere Informationen: IPluginExecutionContext, Grundlegendes zum Ausführungskontext

Organisationswebdienst

Neben den im Ausführungskontext übergebenen Daten können Dataverse Tabellenzeilendaten mithilfe von SDK-Aufrufen an den Organisationswebdienst aus dem Plug-In-Code ausgelesen oder geschrieben werden. Versuchen Sie nicht, die Web-API zu verwenden, da diese in Plug-ins nicht unterstützt wird. Authentifizieren Sie den Benutzer nicht, bevor Sie auf die Webdienste zugreifen, da der Benutzer vor der Ausführung des Plug-ins vorauthentifiziert wird.

Weitere Informationen: Tabellenvorgänge, Meldungen verwenden

Verwenden Sie den folgenden Code, um einen Objektverweis zum Organisationswebdienst zu erhalten:

IOrganizationServiceFactory serviceFactory =
    (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService orgService = serviceFactory.CreateOrganizationService(context.UserId);

Ablaufverfolgungsdienst

Verwenden Sie den Tracing-Dienst, um Nachrichten in die PluginTraceLog-Tabelle zu schreiben, sodass Sie die Protokolle überprüfen können, um zu verstehen, was beim Ausführen des Plug-ins passiert ist.

Wichtig

Sie müssen zuerst die Ablaufverfolgungsprotokollierung in Ihrer Umgebung aktivieren, bevor Sie in die Protokolle schreiben oder sie anzeigen können. Weitere Informationen: Nachverfolgung und Protokollierung

Um in das Tracelog zu schreiben, müssen Sie eine Instanz des Tracing-Dienstes abrufen. Der folgende Code zeigt, wie Sie eine Instanz des Tracing-Dienstes abrufen, indem Sie die IServiceProvider.GetService Methode verwenden.

ITracingService tracingService =
    (ITracingService)serviceProvider.GetService(typeof(ITracingService));

Um die Ablaufverfolgung zu schreiben, verwenden Sie die ITracingService.Trace Methode verwenden.

tracingService.Trace("Write {0} {1}.", "your", "message");

Weitere Informationen finden Sie unter: Ablaufverfolgung verwenden, Ablaufverfolgung und Protokollierung

Sonstige Dienste

Wenn Sie ein Plug-in schreiben, das die Azure Service Bus-Integration nutzt, verwenden Sie den Benachrichtigungsdienst, der die Schnittstelle IServiceEndpointNotificationService implementiert. Diese Schnittstelle wird hier jedoch nicht beschrieben.

Weitere Informationen: Azure-Integration

Alles zusammenfügen

Aus den zuvor beschriebenen Plug-In-Konzepten ergibt sich ein Plug-In-Code, der wie folgt aussieht.

public class MyPlugin : PluginBase
{
  // Constructor
  public MyPlugin(string unsecureConfiguration, string secureConfiguration)
       : base(typeof(MyPlugin))
  { }

  protected override void ExecuteDataversePlugin(ILocalPluginContext localPluginContext)
  {
    if (localPluginContext == null)
    {
      throw new ArgumentNullException(nameof(localPluginContext));
    }

    var context        = localPluginContext.PluginExecutionContext;
    var serviceFactory = localPluginContext.OrgSvcFactory;
    var tracingService = localPluginContext.TracingService;

    try
    {
      // TODO Plug-in business logic goes here. You can access data in the context,
      // and make calls to the Organization web service using the Dataverse SDK.
    }
    catch (FaultException<OrganizationServiceFault> ex)
    {
      throw new InvalidPluginExecutionException("The following error occurred in MyPlugin.", ex);
    }
    catch (Exception ex)
    {
        tracingService.Trace("MyPlugin: error: {0}", ex.ToString());
        throw;
    }
  }
}

Sie können diese beiden Methoden der Plug-In-Implementierung in unserem FollowupPlugin-Codebeispiel überprüfen. Weitere Informationen zur Behandlung von Ausnahmen in Plug-Ins finden Sie unter Behandeln von Ausnahmen in Plug-Ins.

Der Plug-In-Entwurf wirkt sich auf die Leistung aus

Wenn Sie Ihr Plug-in schreiben, ist es wichtig, dass es effizient und schnell ausgeführt wird. Unabhängig davon, wie lange die Ausführung Ihres Plug-Ins dauert, muss der Endbenutzer, der den Nachrichtenvorgang (der Ihr Plug-In ausgelöst hat) aufgerufen hat, warten. Dataverse verarbeitet nicht nur den Nachrichtenvorgang, sondern führt auch alle registrierten synchronen Plug-Ins in der Pipeline aus, einschließlich Ihres Plug-Ins. Wenn die Ausführung von Plug-ins zu lange dauert oder zu viele Plug-ins in einer Pipeline registriert sind, kann diese Auswirkung auf die Leistung dazu führen, dass die Benutzeroberfläche der Anwendung nicht reagiert oder schlimmstenfalls ein Timeout-Fehler mit Pipeline-Rollback eintritt.

Wichtig

Plug-Ins müssen eine Ausführungszeitbegrenzung und Ressourcenbeschränkungen einhalten. Weitere Informationen: Analysieren der Plug-In-Leistung

Typen mit früher Bindung im Plug-In-Code verwenden

Sie können optional Typen mit früher Bindung in Plug-In-Code verwenden. Fügen Sie die generierte Datei mit den Typen in Ihr Plugin-Projekt ein. Alle in der Sammlung InputParameters des Ausführungskontexts bereitgestellten Tabellentypen sind spät gebundene Typen. Sie müssten diese Typen mit später Bindung in solche mit früher Bindung konvertieren.

Wenn Sie wissen, dass der Target Parameter für eine Kontotabelle steht, können Sie zum Beispiel Folgendes tun. In diesem Beispiel ist „Konto“ ein Typ mit früher Bindung.

Account acct = context.InputParameters["Target"].ToEntity<Account>();

Sie sollten aber nie versuchen, den Wert mit einem früh gebundenen Typ festzulegen. Wenn Sie dies tun, tritt ein SerializationException auf.

context.InputParameters["Target"] = new Account() { Name = "MyAccount" }; // WRONG: Do not do this. 

Siehe auch

Verarbeiten von Ausnahmen
Registrieren eines Plug-Ins
Debuggen von Plug-Ins
Lernprogramm: Schreiben und Registrieren eines Plugins
Beste Praktiken und Anleitungen hinsichtlich Plug-In und Workflow-Entwicklung

Hinweis

Können Sie uns Ihre Präferenzen für die Dokumentationssprache mitteilen? Nehmen Sie an einer kurzen Umfrage teil. (Beachten Sie, dass diese Umfrage auf Englisch ist.)

Die Umfrage dauert etwa sieben Minuten. Es werden keine personenbezogenen Daten erhoben. (Datenschutzbestimmungen).