23/11/1998
I Dynamics 365's verden er evnen til at tilpasse og udvide platformens standardfunktionalitet afgørende for at skabe løsninger, der passer perfekt til en virksomheds unikke behov. En af de mest kraftfulde metoder til at opnå dette er ved at bruge plugins. Plugins giver udviklere mulighed for at injicere brugerdefineret forretningslogik på specifikke punkter i platformens databehandlingscyklus. Denne cyklus er kendt som Event Execution Pipeline, og at forstå dens faser er nøglen til at skrive effektive og pålidelige plugins. I denne artikel vil vi fokusere specifikt på Pre-Operation-fasen, en kritisk fase, hvor du kan modificere data, lige før de bliver permanent gemt i databasen.

Hvad er Event Execution Pipeline?
Forestil dig, at hver gang du opretter, opdaterer eller sletter en post i Dynamics 365, starter en usynlig samlebåndsproces. Dette samlebånd er Event Execution Pipeline. Det er opdelt i flere faser, hvor forskellige typer operationer kan udføres. De primære faser for et plugin er:
- Pre-Validation (Fase 10): Dette er det tidligste stadie. Det sker uden for databasetransaktionen. Det bruges typisk til at validere inputdata. Hvis valideringen fejler, kan du kaste en fejl her for at annullere hele operationen, før den overhovedet begynder at interagere med databasen.
- Pre-Operation (Fase 20): Dette er vores hovedfokus. Denne fase kører efter valideringen, men inden systemets hovedoperation udføres. Det vigtigste er, at denne fase kører inden for en database transaktion. Det betyder, at alle ændringer, du foretager her, er en del af den samme atomare operation som hovedhandlingen. Hvis noget fejler senere, rulles dine ændringer tilbage sammen med alt andet.
- Main Operation (Fase 30): Her udfører Dynamics 365-platformen selve kernehandlingen, f.eks. at oprette eller opdatere posten i databasen. Du kan ikke registrere plugins direkte i denne fase.
- Post-Operation (Fase 40): Denne fase kører efter, at hovedoperationen er fuldført og dataene er gemt i databasen. Den kører også inden for databasetransaktionen. Dette stadie bruges typisk til at udføre handlinger, der afhænger af, at den primære post er blevet oprettet (f.eks. for at få dens unikke GUID) og derefter oprette eller opdatere relaterede poster.
Et Dybdyk i Pre-Operation Plugins
Pre-Operation plugins er arbejdshesten, når det kommer til at modificere data, inden de rammer databasen. Fordi de kører inden for databasetransaktionen, sikrer de dataintegritet. Hvis dit plugin f.eks. opdaterer fem felter på en konto, og den efterfølgende systemopdatering fejler af en eller anden grund, vil dine fem feltopdateringer automatisk blive rullet tilbage. Dette forhindrer, at systemet efterlades i en inkonsekvent tilstand.
Den primære anvendelse er at ændre værdierne i de attributter, der sendes til systemet. Når en bruger f.eks. opretter en ny kontaktperson, kan et Pre-Operation plugin opsnappe disse data, ændre et telefonnummerformat, standardisere en adresse eller beregne en værdi for et felt baseret på andre input, alt sammen før den nye kontaktperson nogensinde gemmes.
Praktisk Eksempel: Automatisk formatering af Ticker Symbol
Lad os se på et konkret eksempel. Forestil dig, at vi på en 'Konto' (Account) post har et felt kaldet 'Ticker Symbol'. Vi ønsker at sikre, at hver gang en bruger indtaster et ticker-symbol, bliver det automatisk præfikset med "NYSE: ". Dette er en perfekt opgave for et Pre-Operation plugin.
Koden bag magien
Her er den fulde C#-kode til vores plugin. Vi vil gennemgå den bagefter.
using System; using Microsoft.Xrm.Sdk; namespace Carl.PluginPreOperationSample { public class UpdateAccount: IPlugin { public void Execute(IServiceProvider serviceProvider) { try { // Få fat i udførelseskonteksten fra service provideren. IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); // Tjek om InputParameters indeholder en 'Target' og om det er en Entity. if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { // Hent Target-entiteten. Entity entity = (Entity)context.InputParameters["Target"]; // Tjek om entiteten er en 'account'. if (entity.LogicalName == "account") { // Tjek om feltet 'tickersymbol' er blevet opdateret. if (entity.Attributes.Contains("tickersymbol") == true) { // Hent den nuværende værdi af attributten. var tickersymbol = entity["tickersymbol"].ToString(); // Opdater attributten med den nye, formaterede værdi. entity["tickersymbol"] = "NYSE: " + tickersymbol; } } } } catch (InvalidPluginExecutionException e) { // Håndter eventuelle forventede fejl. throw new InvalidPluginExecutionException("An error has occurred: " + e.Message); } catch (Exception ex) { // Håndter uventede fejl og giv en meningsfuld fejlbesked. throw new InvalidPluginExecutionException("An unexpected error occurred in the UpdateAccount plugin.", ex); } } } } I koden henter vi først `IPluginExecutionContext`. Denne kontekst indeholder al information om den hændelse, der udløste plugin'et, herunder de data, der bliver behandlet. Disse data findes i `InputParameters["Target"]` og er af typen `Entity`. Vores Target-entitet indeholder kun de felter, der bliver oprettet eller ændret, ikke hele posten.
Vi udfører en række sikkerhedstjek for at sikre, at vores kode kun kører, når den skal: når en 'account' opdateres, og når 'tickersymbol'-feltet specifikt er en del af denne opdatering. Derefter henter vi den værdi, brugeren har indtastet, tilføjer vores præfiks og placerer den nye værdi tilbage i `Target`-entiteten. Fordi dette sker i Pre-Operation, vil det være denne modificerede værdi, som Dynamics 365 gemmer i databasen.
Registrering og Debugging
Når koden er skrevet og kompileret, skal plugin'et registreres i Dynamics 365 ved hjælp af Plugin Registration Tool. Her angiver du:
- Message: Create og/eller Update
- Primary Entity: account
- Event Pipeline Stage of Execution: PreOperation
- Execution Mode: Synchronous
Det er kritisk, at Execution Mode er sat til synkron. Asynkrone plugins kører i baggrunden, efter transaktionen er afsluttet, og kan ikke bruges i Pre-Operation-fasen.

Ved debugging kan man se, at plugin'et kører i fase 20, og at `IsInTransaction`-egenskaben på konteksten er `true`, hvilket bekræfter, at vi opererer sikkert inden for databasetransaktionen.
Alternativet: Real-time Workflows som Pre-Operation
For simplere logik kan Real-time Workflows være et alternativ til plugins. De er synkrone og kører også som en del af databasetransaktionen. Dog er deres standardindstillinger for 'Create'-hændelser at køre i Post-Operation (fase 40).
Det er dog muligt at tvinge et Real-time Workflow til at køre i Pre-Operation. Dette kræver en teknisk justering direkte i dataene:
- Find det pågældende workflow i systemet. Hvert workflow er en post i 'workflow'-entiteten.
- Opdater attributten `createstage` for dette workflow fra standardværdien `40` (Post-Operation) til `20` (Pre-Operation). Dette skal gøres via kode (f.eks. med SDK) eller et værktøj som XrmToolBox.
Når dette er gjort, vil dit Real-time Workflow opføre sig som et Pre-Operation plugin. Hvis du f.eks. opretter et workflow, der sætter en 'Salutation' baseret på køn, vil denne ændring ske, *før* posten oprettes. Ser man på revisionshistorikken, vil posten blive oprettet med den korrekte 'Salutation' fra start. Hvis workflowet kørte i Post-Operation, ville man se to separate hændelser: først oprettelsen af posten, og derefter en opdatering fra workflowet.
Sammenligningstabel: Plugin vs. Real-time Workflow
| Egenskab | Pre-Operation Plugin | Real-time Workflow (i Pre-Op) |
|---|---|---|
| Kompleksitet | Høj (kræver C# og Visual Studio) | Lav til medium (visuel designer, men kan kræve custom workflow activities) |
| Fleksibilitet | Meget høj, fuld adgang til .NET framework | Begrænset til de handlinger, der er tilgængelige i workflow-designeren |
| Ydeevne | Generelt hurtigere, da det er kompileret kode | Kan have et lille overhead |
| Vedligeholdelse | Kræver en udvikler for at lave ændringer | Kan ofte justeres af en systemadministrator |
Ofte Stillede Spørgsmål (FAQ)
Hvad er den primære forskel mellem Pre-Validation og Pre-Operation?
Den afgørende forskel er databasetransaktionen. Pre-Validation (fase 10) sker før transaktionen starter. Det er ideelt til at afvise en hel operation med en fejlbesked, hvis input er ugyldigt. Pre-Operation (fase 20) sker inden for transaktionen og er designet til at modificere data, der er på vej til at blive gemt, med sikkerheden om, at ændringerne rulles tilbage, hvis noget går galt senere i processen.
Kan et Pre-Operation plugin se værdier, som de var, før ændringen?
Ja, men kun ved en 'Update'-handling. I dette scenarie kan du registrere et 'Pre-image'. Dette er et øjebliksbillede af posten, som den så ud, før ændringerne blev foretaget. Du kan så sammenligne værdierne i Pre-image med de nye værdier i Target-entiteten for at bygge kompleks logik. For en 'Create'-handling findes der intet Pre-image, da posten ikke eksisterede før.
Hvorfor kan jeg ikke få postens GUID i et Pre-Operation plugin på en 'Create'-handling?
Fordi plugin'et kører, før hovedhandlingen (oprettelsen i databasen) er udført. GUID'et for en post tildeles først under selve oprettelsen i databasen (Main Operation). Hvis du har brug for postens GUID til at udføre yderligere logik, skal du bruge et Post-Operation plugin.
Hvis du vil læse andre artikler, der ligner Dynamics 365: En Dybdegående Guide til Plugins, kan du besøge kategorien Teknologi.
