Exercise - Write your first plug-in
In this scenario, an organization needs to ensure that phone number data is entered in a consistent format. To achieve this objective, you'll create a plug-in to run on create/update that strips out all non-numeric characters from a phone number before saving to Dataverse. You'll then create another plug-in that will run on Contact retrieve/retrievemultiple to reformat the phone number to include parentheses and dashes, if the data exists.
Exercise 1: Create/update plug-in
In this exercise, you'll create a plug-in that will run on create and update. This plug-in will strip out all non-numeric characters from a phone number.
Each exercise consists of a scenario and learning objectives. The scenario describes the purpose of the exercises, while the objectives are listed and have bullet points.
Note
If you don't have the Dynamics 365 SDK tools, see Download tools from NuGet to download.
Task 1: Create a plug-in
Start Visual Studio 2022.
Select File > New > Project.
Select Class Library (.NET Framework) and select Next.
Enter D365PackageProject for Project Name, select a location to save the project, select .NET Framework 4.6.2 for Framework, and then select Create.
Right-click the project and select Manage NuGet Packages.
Select the Browse tab, search for and select microsoft.crmsdk.coreassemblies, and then select Install.
Read the license terms and then select Accept if you agree.
Close the NuGet package manager.
Right-click Class1.cs and Delete.
Right-click the project and then select Add > Class.
Name the new class PreOperationFormatPhoneCreateUpdate and select Add.
Add the using statements to the new class as follows:
using Microsoft.Xrm.Sdk; using System.Text.RegularExpressions;
Make the class public and implement the IPlugin interface.
Implement the interface member.
Your class should now look like the following image.
Task 2: Format a phone number
Get the execution context from the service provider. Replace the exception in the Execute method with the following snippet.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
Check the input parameter for Target. Add the following snippet to the Execute method.
if (!context.InputParameters.ContainsKey("Target")) throw new InvalidPluginExecutionException("No target found");
Add the following snippet to the Execute method. This snippet will get the target entity from the input parameter and then check if its attributes contain telephone1 (Business Phone for Contacts, Phone for Accounts).
var entity = context.InputParameters["Target"] as Entity; if (!entity.Attributes.Contains("telephone1")) return;
Add the following snippet to the Execute function. This snippet will remove all non-numeric characters from the user-provided phone number.
string phoneNumber = (string)entity["telephone1"]; var formattedNumber = Regex.Replace(phoneNumber, @"[^\d]", "");
Set telephone1 to the formatted phone number. Add the following snippet to the Execute method.
entity["telephone1"] = formattedNumber;
The Execute method should now look like the following image.
Right-click the project and select Properties.
Select the Signing tab and select New Key File.
Enter contoso.snk in the Key file name field, clear the Protect my key file with a password check box, and then select OK.
Close the Properties tab.
Build the project and make sure that the build succeeds.
Task 3: Register a plug-in and steps
Note
If you don't have the Dynamics 365 SDK tools, see Download tools from NuGet to download.
Start the plug-in registration tool application.
Select Create New Connection.
Select Microsoft 365, select the Show Advanced check box, provide your credentials, and then select Login.
Select Register and then select Register New Assembly.
Select Browse.
Browse to the Bin > Debug folder of the class library that you created, select D365PackageProject.dll, and then select Open.
Select Register Selected Plugins.
Select OK.
Expand the newly registered assembly.
Right-click the plug-in and select Register New Step.
Select Create for Message and select contact for Primary Entity.
Select PreOperation for Event Pipeline Stage of Execution and then select Register New Step.
Select Close.
Right-click the plug-in and select Register New Step again.
Select Update for Message, select contact for Primary Entity, and then select the Attributes lookup.
Clear the Select All check box, select the Business Phone check box, and then select OK.
Select PreOperation for Event Pipeline Stage of Execution and then select Register New Step.
Task 4: Test the plug-in
Go to your Maker Portal and make sure you have the correct environment selected.
Select Apps and launch the Fundraiser application.
Select Dashboard and open one of the contacts.
Select + New.
Enter Test for First Name, Contact for Last Name, (123)-555-0100 for Business Phone, and then select Save.
The record should be saved, and the Business Phone should show only the numeric values.
Change the Business Phone to 001-123-555-0100 and wait for a few seconds.
The record should be updated, and the Business Phone should show only the numeric values.
Exercise 2: Create/Retrieve multiple plug-ins
In this exercise, you'll create a plug-in that will run on retrieve and retrieve multiple. This plug-in will add parentheses and dashes to the phone numbers.
Each exercise consists of a scenario and learning objectives. The scenario describes the purpose of the exercises, while the objectives are listed and have bullet points.
Task 1: Create a plug-in
Start Visual Studio.
Open the project that you created in Exercise 1.
Right-click the project and select Add > Class.
In the Name field, enter PostOperationFormatPhoneOnRetrieveMultiple for the class and then select Add.
Add the using statements to the new class as follows:
using Microsoft.Xrm.Sdk;
Make the class public and implement the IPlugin interface.
Implement the interface member. Your class should now look like the following image.
Task 2: Format phone number for retrieve
Get the execution context from the service provider. Replace the exception in the Execute method with the following snippet.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
Check if the message name is Retrieve or RetrieveMultiple. Add the following snippet to the Execute method.
if (context.MessageName.Equals("Retrieve")) { } else if(context.MessageName.Equals("RetrieveMultiple")) { }
Check if the output parameters contain a business entity and that it's a type of entity. Paste the following snippet inside the
if
retrieve condition.if (!context.OutputParameters.Contains("BusinessEntity") && context.OutputParameters["BusinessEntity"] is Entity) throw new InvalidPluginExecutionException("No business entity found");
Get the entity and check if it contains telephone1 field. Add the following snippet inside the
if
retrieve condition.var entity = (Entity)context.OutputParameters["BusinessEntity"]; if (!entity.Attributes.Contains("telephone1")) return;
Add the following snippet to the
if retrieve
condition. This snippet will try to parse telephone1 as long and will return if the parsing doesn't succeed.if (!long.TryParse(entity["telephone1"].ToString(), out long phoneNumber)) return;
Format the phone number by adding parentheses and dashes. Add the following snippet inside the
if retrieve
condition.var formattedNumber = String.Format("{0:(###) ###-####}", phoneNumber); entity["telephone1"] = formattedNumber;
The retrieve part of the Execute method should now look like the following image.
Task 3: Format phone number for retrieve multiple
Add the following snippet to the inside of the
retrieve multiple
condition. This snippet will check if the output parameters contain BusinessEntityCollection and if it is of the type EntityCollection.if(!context.OutputParameters.Contains("BusinessEntityCollection") && context.OutputParameters ["BusinessEntityCollection"] is EntityCollection) throw new InvalidPluginExecutionException("No business entity collection found");
Get the entity collection from the output parameters. Add the following snippet inside the
retrieve multiple
condition.var entityCollection = (EntityCollection)context.OutputParameters["BusinessEntityCollection"];
Iterate through each entity in the entity collection.
foreach (var entity in entityCollection.Entities) { }
Add the following snippet inside the
foreach
condition. This snippet will do the same thing that theretrieve
condition is doing.if (entity.Attributes.Contains("telephone1") && entity["telephone1"] != null) { if (long.TryParse(entity["telephone1"].ToString(), out long phoneNumber)) { var formattedNumber = String.Format("{0:(###) ###-####}", phoneNumber); entity["telephone1"] = formattedNumber; } }
The retrieve multiple part of the Execute method should now look like the following image.
Rebuild the project and make sure that the build succeeds.
Task 4: Update plug-in assembly and register steps
Start the plug-in registration tool and select Create New Connection.
Select Microsoft 365, provide your credentials, and then select Login.
Select the assembly that you registered in Exercise 1 and then select Update.
Select Browse.
Browse to the debug folder of your project, select D365PackageProject.dll, and then select Open.
Select the plug-ins and then select Update Selected Plugins.
Select OK.
Right-click the new plug-in and select Register New Step.
Select Retrieve for Message, select contact for Primary Entity, and then select PostOperation for Event Pipeline Stage of Execution. Make sure that you have Synchronous selected for Execution Mode and then select Register New Step.
Right-click the plug-in and select Register New Step again.
Select RetrieveMultiple for Message, select contact for Primary Entity, and then select PostOperation for Event Pipeline Stage of Execution. Make sure that you have Synchronous for Execution Mode selected, and then select Register New Step.
Task 5: Test the plug-in
Go to your Maker Portal and make sure you are in the correct environment.
Select Apps. Then select the Fundraiser application, and then select Edit. You'll add the Contact table to the application.
Select + New page.
Select Dataverse table and then select Next.
Select Existing table. Then select the Contact table, and then select Add.
Select Play.
Select Save and continue.
Select Play again.
Select Contacts.
The existing records that weren't saved with the new format won't change. Select + New.
Provide the following information and then select Save. The record should be saved, and the plug-in should apply the new format.
Select Contacts again. The record that you created should have the new format.
Select one of the existing contacts to open it.
Edit the Business Phone, as follows:
Select Save. The new format should be applied. Select Contacts one more time.
The edited phone should have the new format.