Zum Inhalt wechseln

Wie Sie Dataverse-Audits in Power Automate abrufen

Technology

27 März 2023 - 5 Minuten lesen

2907 Dataverse Audits Blog Post 416X300
Amadeusz Nowak Software Developer  

Er ist ein Power Platform Entwickler mit über 5 Jahren Erfahrung. Außerhalb der Bürozeiten ist Amadeusz ein Amateur-Fußballanalyst und ein begeisterter PC-Bauer.

Alle Beiträge von Amadeusz anzeigen

1394 DE Resources Thumbs

Teilen

Dies ist der dritte Teil meines Leitfadens zu benutzerdefinierten Überwachungsprotokollen in Power Apps. Im vorherigen Artikel sind wir die Vorbereitungen für den Entwicklungsprozess durchlaufen. In diesem Teil zeige ich Ihnen, wie Sie Ihren Power Automate-Flow mit dem Azure Key Vault verbinden und Zugriff auf Audits innerhalb von Dataverse erhalten. 

Power Automate-Flow 

Endlich ist es an der Zeit, etwas zu programmieren. Ich werde demonstrieren, wie Aktualisierungen von Datensätzen in der Zielentität gehandhabt werden. Sie können diesen Ablauf erweitern, um das Hinzufügen und Löschen von Zeilen abzudecken und separate Flows für neue Zeilen und das Löschen von Zeilen erstellen. Ich bevorzuge den letzteren Ansatz, da er einfacher zu debuggen und zu warten ist. 

Flow-Typ und Trigger 

Wir beginnen mit der Erstellung eines „Automated Flow“ mit dem Dataverse-Konnektor als Auslöser,

Im Moment sind wir nur an Änderungen interessiert, also setzen wir „Change type“ auf „Modified“, „Table name“ wird unsere Hauptentität sein, während „Scope“ auf „Organization“ festgelegt werden muss, um alle an den Datensätzen vorgenommenen Änderungen abzudecken - egal wer sie gemacht hat. 

Wir werden unseren Trigger auf nur die Spalten beschränken, in denen wir Änderungen verfolgen möchten, indem wir sie nach ihren logischen Namen unter „Select columns“ auflisten. 

Mehr dazu 

Variablen 

Bevor wir fortfahren, initialisieren wir einige Variablen: 

  • arrColumns; Array  
  • strChanegs; String  
  • strOld; String  
  • strNew; String  
  • strEmpty; String  

Alle sollten im Moment der Initialisierung leer sein, mit Ausnahme von arrColumns. Schauen wir uns diesen genauer an. 

Sie müssen eine Reihe mit Metadaten zu allen Spalten erstellen, in denen Sie Änderungen protokollieren möchten. Es wird später benötigt, um alle Änderungen zu durchlaufen, die Sie von Ihrer HTTP-Anfrage erhalten. 

Das Objekt in Ihrer Spalte (array) ist ein JSON dieser Struktur: 

{

 "logical_name": "",

 "display_name": "",

 "type": "",

 "related_table": "",

 "related_column": ""

}

Wo: 

  • logical_name — logischer Name Ihrer Spalte 
  • display_name — Anzeigename Ihrer Spalte 
  • type — Spaltentyp 
  • related_table — logischer Name der zugehörigen Tabelle (optional, abhängig vom Spaltentyp, wird für das Suchen und Auswählen verwendet) 
  • related_column — logischer Name der Hauptspalte aus der zugehörigen Tabellenentität (optional, abhängig vom Spaltentyp, wird nur für Suchvorgänge verwendet) 

Mehr dazu 

In meinem Fall wird die Spalte so aussehen: 

[

 {

  "logical_name": "anowak_name",

  "display_name": "Name",

  "type": "Text",

  "related_table": "",

  "related_column": ""

 },

 {

  "logical_name": "anowak_organization",

  "display_name": "Organization",

  "type": "Choice",

  "related_table": "anowak_organization",

  "related_column": ""

 },

 {

  "logical_name": "anowak_leader",

  "display_name": "Leader",

  "type": "Lookup",

  "related_table": "anowak_cast",

  "related_column": "anowak_name"

 },

 {

  "logical_name": "anowak_joined",

  "display_name": "Joined",

  "type": "Date", "related_table": "",

  "related_column": ""

 },

 {

  "logical_name": "statecode",

  "display_name": "Status",

  "type": "Status",

  "related_table": "",

  "related_column": ""

  }

]

An dieser Stelle sollte Ihr Flow folgendermaßen aussehen: 

Zugriff auf den Key Vault 

Wenn Sie versuchen, Umgebungsvariablen vom Typ „Secret“ zu verwenden, werden Sie schnell feststellen, dass sie nicht auf der Liste der dynamischen Inhalte stehen. Um auf den Key Vault zuzugreifen sowie die Client-ID und das Geheimnis abzurufen, müssen Sie eine ungebundene Aktion ausführen. 

Mehr dazu 

Dazu erstellen Sie die Aktion „Perform an unbound action“. Lassen Sie uns „Action Name“ auf „RetrieveEnvironmentVariableSecretValue“ setzen und im Feld „EnvironmentVariableName“ den logischen Namen der Variablen angeben, die Ihre Client-ID speichert. 

Als Nächstes müssen Sie zu den „Settings“ gehen und „Secure Outputs“ aktivieren, um sicherzustellen, dass Ihre Geheimnisse nicht im Ausführungsverlauf des Flows offengelegt werden. 

Anschließend müssen Sie diesen Vorgang für das Client Secret wiederholen. Nun sollten diese 2 Aktionen am Ende Ihres Flows stehen.

HTTP-Anfrage  

Es ist an der Zeit, die Web-API zu nutzen, um Details über die letzte Änderung am Datensatz zu erhalten. 

Sie beginnen mit dem Verfassen einer HTTP-Anfrage, um die neueste Prüfprotokoll-ID abzurufen, die Sie später verwenden, um Details über das spezifische Prüfprotokoll zu erhalten. 

Packen wir das aus. 

Ihre Anfrage beginnt mit der Umgebungs-URL. Zu Beginn haben wir eine Variable zum Speichern dieser URL erstellt, falls Sie diese Lösung in eine andere Umgebung verschieben möchten. Dann verwenden Sie dynamische Inhalte und rufen den Wert aus Ihrer Variablen ab. 

@{parameters('EnvironmentURL (anowak_EnvironmentURL)')}

Als Nächstes fordern Sie den Service über die Web-API für alle Audits an und filtern ihn nach einer eindeutigen Kennung der Hauptentität. 

(anowak_EnvironmentURL)')}api/data/v9.0/audits?$filter=_objectid_value eq @{triggerOutputs()?['body/anowak_castid']}

Lassen Sie uns abschließend die Audits nach „erstellt am“-Eigenschaft in absteigender Reihenfolge anordnen und sie so beschränken, dass sie nur die neuesten enthalten. Am Ende sollte die Anfrage so aussehen: 

@{parameters('EnvironmentURL(anowak_EnvironmentURL)')}api/data/v9.0/audits?$filter=_objectid_value eq @{triggerOutputs()?['body/anowak_castid']}&$orderby=createdon desc&$top=1

Nun können Sie Ihre http Anfrage-Aktion starten.  

Wir nutzen die „GET“ -Methode, URI wird zum Output von „Compose“ -Aktionen im vorherigen Schritt und Sie werden diese Anfrage mit „Active Directory OAuth“ authentifizieren:  

Tenant — Tenant ID in der Variable gespeichert 

Audience — Umgebungs-URL aus der Variable  

Client ID — Ergebnis der ungebundenen Aktion zum Abrufen der Client ID aus dem Key Vault

@{outputs('Perform_an_unbound_action_-_get_client_id')?['body/EnvironmentVariableSecretValue']}

Secret — Ergebnis der ungebundenen Aktion zum Abrufen des Geheimnisses aus dem Key Vault

@{outputs('Perform_an_unbound_action_-_get_client_secret')?['body/EnvironmentVariableSecretValue']}

Obwohl Sie nur ein einziges Audit-Protokoll abrufen, erhalten Sie dennoch JSON mit einem Array, das nur ein Objekt enthält. Um Ihre Audit-ID zu erhalten, müssen wir zuerst diesen singulären Wert abrufen. 

Dies ist das Schema der Antwort, die Sie von dieser Anfrage erhalten: 

{

    "type": "object",

    "properties": {

        "@@odata.context": {

            "type": "string"

        },

        "value": {

            "type": "array",

            "items": {

                "type": "object",

                "properties": {

                    "_objectid_value": {

                        "type": "string"

                    },

                    "_userid_value": {

                        "type": "string"

                    },

                    "operation": {

                        "type": "integer"

                    },

                    "createdon": {

                        "type": "string"

                    },

                    "auditid": {

                        "type": "string"

                    },

                    "changedata": {

                        "type": "string"

                    },

                    "attributemask": {

                        "type": "string"

                    },

                    "action": {

                        "type": "integer"

                    },

                    "objecttypecode": {

                        "type": "string"

                    },

                    "transactionid": {

                        "type": "string"

                    },

                    "_regardingobjectid_value": {},

                    "useradditionalinfo": {},

                    "_callinguserid_value": {},

                    "versionnumber": {}

                },

                "required": [

                    "_objectid_value",

                    "_userid_value",

                    "operation",

                    "createdon",

                    "auditid",

                    "changedata",

                    "attributemask",

                    "action",

                    "objecttypecode",

                    "transactionid",

                    "_regardingobjectid_value",

                    "useradditionalinfo",

                    "_callinguserid_value",

                    "versionnumber"

                ]

            }

        }

    }

}

Was Sie nutzen sollten: 

last(body('HTTP_-_get_audit_id')?['value'])?['auditid']  

Nun ist es an der Zeit, eine weitere Anfrage zu verfassen, diesmal um die Details des Audit-Protokolls abzurufen. 

Wie zuvor erhalten Sie die Umgebungs-URL. Anschließend erstellen Sie mithilfe der Web-API eine Abfrage, um Audits nach der Audit-ID zu filtern, die Sie von der vorherigen HTTP-Anforderung erhalten haben. Dazu verwenden Sie den obigen Wert. Schließlich können Sie Einzelheiten zu diesem Audit anfordern. 

@{parameters('EnvironmentURL(anowak_EnvironmentURL)')}api/data/v9.0/audits(@{last(body('HTTP_-_get_audit_id')?['value'])?['auditid']})/Microsoft.Dynamics.CRM.RetrieveAuditDetails()

Wenn der neue Request fertig ist, verwenden Sie die HTTP-Aktion erneut in ähnlicher Weise wie zuvor. Der einzige Unterschied wird der URI sein, er wird der Output der letzten „Compose“-Aktion sein. 

Schauen wir uns das Beispiel der Antwort an: 

{

  "@odata.context": "https://org4a297f94.crm.dynamics.com/api/data/v9.0/$metadata#Microsoft.Dynamics.CRM.RetrieveAuditDetailsResponse",

  "AuditDetail": {

    "@odata.type": "#Microsoft.Dynamics.CRM.AttributeAuditDetail",

    "InvalidNewValueAttributes": [],

    "LocLabelLanguageCode": 0,

    "DeletedAttributes": {

      "Count": 0,

      "Keys": [],

      "Values": []

    },

    "OldValue": {

      "@odata.type": "#Microsoft.Dynamics.CRM.anowak_cast"

    },

    "NewValue": {

      "@odata.type": "#Microsoft.Dynamics.CRM.anowak_cast",

      "anowak_joined": "2006-12-08T23:00:00Z"

    }

  }

}

Die Antworten unterscheiden sich je nach den Änderungen, die am Datensatz vorgenommen wurden. In diesem Beispiel sehen Sie, dass der Spalte „Joined“, die zuvor leer war, ein neuer Wert zugewiesen wurde. 

Jetzt müssen Sie nur noch eine Liste mit alten und neuen Werten aus der Antwort abrufen. 

body('HTTP_-_get_audit_log')?['AuditDetail']?['OldValue']

body('HTTP_-_get_audit_log')?['AuditDetail']?['NewValue']

Und damit möchte ich den dritten Teil dieses Ratgebers abschließen. Im nächsten Teil zeige ich Ihnen, wie Sie mit verschiedenen Spaltendatentypen arbeiten und Änderungen in Ihrer benutzerdefinierten Überwachungslösung protokollieren können. 

1394 DE Resources Thumbs
Amadeusz Nowak Software Developer  

Er ist ein Power Platform Entwickler mit über 5 Jahren Erfahrung. Außerhalb der Bürozeiten ist Amadeusz ein Amateur-Fußballanalyst und ein begeisterter PC-Bauer.

Alle Beiträge von Amadeusz anzeigen

Was Sie noch interesieren könnte

Kontakt

Starten Sie Ihr Projekt mit Objectivity

CTA Pattern - Contact - Middle